1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 38eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 54ef0f4d6SPekka Enberg #include "kvm/mutex.h" 646aa8d69SPekka Enberg #include "kvm/util.h" 705d1a2a6SAsias He #include "kvm/term.h" 8e557eef9SPekka Enberg #include "kvm/kvm.h" 9d28abb58SWill Deacon #include "kvm/fdt.h" 1013a7760fSPekka Enberg 113fdf659dSSasha Levin #include <linux/types.h> 124e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 134e49b05bSCyrill Gorcunov 142932c9ebSPekka Enberg #include <pthread.h> 1513a7760fSPekka Enberg 16d4b02a37SThomas Gleixner /* 17d4b02a37SThomas Gleixner * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel 18d4b02a37SThomas Gleixner * expects that for autodetection. 19d4b02a37SThomas Gleixner */ 20d4b02a37SThomas Gleixner #define FIFO_LEN 64 21d4b02a37SThomas Gleixner #define FIFO_MASK (FIFO_LEN - 1) 22d4b02a37SThomas Gleixner 23d4b02a37SThomas Gleixner #define UART_IIR_TYPE_BITS 0xc0 24d4b02a37SThomas Gleixner 2546aa8d69SPekka Enberg struct serial8250_device { 26d3476f7dSSasha Levin struct mutex mutex; 271add4b76SSasha Levin u8 id; 282932c9ebSPekka Enberg 293fdf659dSSasha Levin u16 iobase; 303fdf659dSSasha Levin u8 irq; 31f6b8ccc1SThomas Gleixner u8 irq_state; 328dfae8beSThomas Gleixner int txcnt; 33d4b02a37SThomas Gleixner int rxcnt; 34d4b02a37SThomas Gleixner int rxdone; 35d4b02a37SThomas Gleixner char txbuf[FIFO_LEN]; 36d4b02a37SThomas Gleixner char rxbuf[FIFO_LEN]; 3776b4a122SPekka Enberg 383fdf659dSSasha Levin u8 dll; 393fdf659dSSasha Levin u8 dlm; 403fdf659dSSasha Levin u8 iir; 413fdf659dSSasha Levin u8 ier; 423fdf659dSSasha Levin u8 fcr; 433fdf659dSSasha Levin u8 lcr; 443fdf659dSSasha Levin u8 mcr; 453fdf659dSSasha Levin u8 lsr; 463fdf659dSSasha Levin u8 msr; 473fdf659dSSasha Levin u8 scr; 4846aa8d69SPekka Enberg }; 4946aa8d69SPekka Enberg 50f3efa592SLiming Wang #define SERIAL_REGS_SETTING \ 51f3efa592SLiming Wang .iir = UART_IIR_NO_INT, \ 52f3efa592SLiming Wang .lsr = UART_LSR_TEMT | UART_LSR_THRE, \ 53f3efa592SLiming Wang .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \ 54f3efa592SLiming Wang .mcr = UART_MCR_OUT2, 55f3efa592SLiming Wang 56e62c18deSPekka Enberg static struct serial8250_device devices[] = { 57c6a69c61SPekka Enberg /* ttyS0 */ 58c6a69c61SPekka Enberg [0] = { 59d3476f7dSSasha Levin .mutex = MUTEX_INITIALIZER, 602932c9ebSPekka Enberg 611add4b76SSasha Levin .id = 0, 62c6a69c61SPekka Enberg .iobase = 0x3f8, 63e557eef9SPekka Enberg .irq = 4, 64e557eef9SPekka Enberg 65f3efa592SLiming Wang SERIAL_REGS_SETTING 66c6a69c61SPekka Enberg }, 67e62c18deSPekka Enberg /* ttyS1 */ 68e62c18deSPekka Enberg [1] = { 69d3476f7dSSasha Levin .mutex = MUTEX_INITIALIZER, 702932c9ebSPekka Enberg 711add4b76SSasha Levin .id = 1, 72e62c18deSPekka Enberg .iobase = 0x2f8, 73e62c18deSPekka Enberg .irq = 3, 74133bedc1SPekka Enberg 75f3efa592SLiming Wang SERIAL_REGS_SETTING 76e62c18deSPekka Enberg }, 77e62c18deSPekka Enberg /* ttyS2 */ 78e62c18deSPekka Enberg [2] = { 79d3476f7dSSasha Levin .mutex = MUTEX_INITIALIZER, 802932c9ebSPekka Enberg 811add4b76SSasha Levin .id = 2, 82e62c18deSPekka Enberg .iobase = 0x3e8, 83e62c18deSPekka Enberg .irq = 4, 84133bedc1SPekka Enberg 85f3efa592SLiming Wang SERIAL_REGS_SETTING 86e62c18deSPekka Enberg }, 87bf459c83SPekka Enberg /* ttyS3 */ 88bf459c83SPekka Enberg [3] = { 89d3476f7dSSasha Levin .mutex = MUTEX_INITIALIZER, 90bf459c83SPekka Enberg 911add4b76SSasha Levin .id = 3, 92bf459c83SPekka Enberg .iobase = 0x2e8, 93bf459c83SPekka Enberg .irq = 3, 94bf459c83SPekka Enberg 95f3efa592SLiming Wang SERIAL_REGS_SETTING 96bf459c83SPekka Enberg }, 9746aa8d69SPekka Enberg }; 9846aa8d69SPekka Enberg 992651ea58SSasha Levin static void serial8250_flush_tx(struct kvm *kvm, struct serial8250_device *dev) 100d4b02a37SThomas Gleixner { 101d4b02a37SThomas Gleixner dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; 102d4b02a37SThomas Gleixner 103d4b02a37SThomas Gleixner if (dev->txcnt) { 1042651ea58SSasha Levin term_putc(dev->txbuf, dev->txcnt, dev->id); 105d4b02a37SThomas Gleixner dev->txcnt = 0; 106d4b02a37SThomas Gleixner } 107d4b02a37SThomas Gleixner } 108d4b02a37SThomas Gleixner 109f6b8ccc1SThomas Gleixner static void serial8250_update_irq(struct kvm *kvm, struct serial8250_device *dev) 110f6b8ccc1SThomas Gleixner { 111f6b8ccc1SThomas Gleixner u8 iir = 0; 112f6b8ccc1SThomas Gleixner 113d4b02a37SThomas Gleixner /* Handle clear rx */ 114d4b02a37SThomas Gleixner if (dev->lcr & UART_FCR_CLEAR_RCVR) { 115d4b02a37SThomas Gleixner dev->lcr &= ~UART_FCR_CLEAR_RCVR; 116d4b02a37SThomas Gleixner dev->rxcnt = dev->rxdone = 0; 117d4b02a37SThomas Gleixner dev->lsr &= ~UART_LSR_DR; 118d4b02a37SThomas Gleixner } 119d4b02a37SThomas Gleixner 120d4b02a37SThomas Gleixner /* Handle clear tx */ 121d4b02a37SThomas Gleixner if (dev->lcr & UART_FCR_CLEAR_XMIT) { 122d4b02a37SThomas Gleixner dev->lcr &= ~UART_FCR_CLEAR_XMIT; 123d4b02a37SThomas Gleixner dev->txcnt = 0; 124d4b02a37SThomas Gleixner dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; 125d4b02a37SThomas Gleixner } 126d4b02a37SThomas Gleixner 127f6b8ccc1SThomas Gleixner /* Data ready and rcv interrupt enabled ? */ 128f6b8ccc1SThomas Gleixner if ((dev->ier & UART_IER_RDI) && (dev->lsr & UART_LSR_DR)) 129f6b8ccc1SThomas Gleixner iir |= UART_IIR_RDI; 130f6b8ccc1SThomas Gleixner 131f6b8ccc1SThomas Gleixner /* Transmitter empty and interrupt enabled ? */ 132f6b8ccc1SThomas Gleixner if ((dev->ier & UART_IER_THRI) && (dev->lsr & UART_LSR_TEMT)) 133f6b8ccc1SThomas Gleixner iir |= UART_IIR_THRI; 134f6b8ccc1SThomas Gleixner 135f6b8ccc1SThomas Gleixner /* Now update the irq line, if necessary */ 136f6b8ccc1SThomas Gleixner if (!iir) { 137f6b8ccc1SThomas Gleixner dev->iir = UART_IIR_NO_INT; 138f6b8ccc1SThomas Gleixner if (dev->irq_state) 139f6b8ccc1SThomas Gleixner kvm__irq_line(kvm, dev->irq, 0); 140f6b8ccc1SThomas Gleixner } else { 141f6b8ccc1SThomas Gleixner dev->iir = iir; 142f6b8ccc1SThomas Gleixner if (!dev->irq_state) 143f6b8ccc1SThomas Gleixner kvm__irq_line(kvm, dev->irq, 1); 144f6b8ccc1SThomas Gleixner } 145f6b8ccc1SThomas Gleixner dev->irq_state = iir; 1468dfae8beSThomas Gleixner 1478dfae8beSThomas Gleixner /* 1488dfae8beSThomas Gleixner * If the kernel disabled the tx interrupt, we know that there 1498dfae8beSThomas Gleixner * is nothing more to transmit, so we can reset our tx logic 1508dfae8beSThomas Gleixner * here. 1518dfae8beSThomas Gleixner */ 152d4b02a37SThomas Gleixner if (!(dev->ier & UART_IER_THRI)) 1532651ea58SSasha Levin serial8250_flush_tx(kvm, dev); 154f6b8ccc1SThomas Gleixner } 155f6b8ccc1SThomas Gleixner 156a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE 0 157a428f72eSPekka Enberg 158a428f72eSPekka Enberg static int sysrq_pending; 159a428f72eSPekka Enberg 16043835ac9SSasha Levin static void serial8250__sysrq(struct kvm *kvm, struct serial8250_device *dev) 161a428f72eSPekka Enberg { 162a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR | UART_LSR_BI; 163226e727bSSasha Levin dev->rxbuf[dev->rxcnt++] = sysrq_pending; 164a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_NONE; 165a428f72eSPekka Enberg } 166a428f72eSPekka Enberg 167d4b02a37SThomas Gleixner static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev, 168d4b02a37SThomas Gleixner bool handle_sysrq) 169251cf9a6SPekka Enberg { 170251cf9a6SPekka Enberg int c; 171251cf9a6SPekka Enberg 172d4b02a37SThomas Gleixner if (dev->mcr & UART_MCR_LOOP) 173db34045cSPekka Enberg return; 174db34045cSPekka Enberg 175d4b02a37SThomas Gleixner if ((dev->lsr & UART_LSR_DR) || dev->rxcnt) 176d4b02a37SThomas Gleixner return; 177d4b02a37SThomas Gleixner 178d4b02a37SThomas Gleixner if (handle_sysrq && sysrq_pending) { 17943835ac9SSasha Levin serial8250__sysrq(kvm, dev); 180a428f72eSPekka Enberg return; 181a428f72eSPekka Enberg } 182a428f72eSPekka Enberg 1832651ea58SSasha Levin if (kvm->cfg.active_console != CONSOLE_8250) 1842651ea58SSasha Levin return; 1852651ea58SSasha Levin 1862651ea58SSasha Levin while (term_readable(dev->id) && 187d4b02a37SThomas Gleixner dev->rxcnt < FIFO_LEN) { 188251cf9a6SPekka Enberg 1894346fd8fSSasha Levin c = term_getc(kvm, dev->id); 19005d1a2a6SAsias He 191251cf9a6SPekka Enberg if (c < 0) 192d4b02a37SThomas Gleixner break; 193d4b02a37SThomas Gleixner dev->rxbuf[dev->rxcnt++] = c; 194251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 195251cf9a6SPekka Enberg } 196d4b02a37SThomas Gleixner } 197251cf9a6SPekka Enberg 198f6b8ccc1SThomas Gleixner void serial8250__update_consoles(struct kvm *kvm) 1998bb34e0dSPekka Enberg { 200479de16fSCyrill Gorcunov unsigned int i; 2011add4b76SSasha Levin 202479de16fSCyrill Gorcunov for (i = 0; i < ARRAY_SIZE(devices); i++) { 2031add4b76SSasha Levin struct serial8250_device *dev = &devices[i]; 204934c193bSPekka Enberg 2054ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2062932c9ebSPekka Enberg 207d4b02a37SThomas Gleixner /* Restrict sysrq injection to the first port */ 208d4b02a37SThomas Gleixner serial8250__receive(kvm, dev, i == 0); 209251cf9a6SPekka Enberg 210f6b8ccc1SThomas Gleixner serial8250_update_irq(kvm, dev); 2112932c9ebSPekka Enberg 2124ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2138bb34e0dSPekka Enberg } 2141add4b76SSasha Levin } 2158bb34e0dSPekka Enberg 216226e727bSSasha Levin void serial8250__inject_sysrq(struct kvm *kvm, char sysrq) 217a428f72eSPekka Enberg { 218226e727bSSasha Levin sysrq_pending = sysrq; 219a428f72eSPekka Enberg } 220a428f72eSPekka Enberg 2214123ca55SMarc Zyngier static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 222d4b02a37SThomas Gleixner void *data, int size) 22313a7760fSPekka Enberg { 224d28abb58SWill Deacon struct serial8250_device *dev = ioport->priv; 2253fdf659dSSasha Levin u16 offset; 2262932c9ebSPekka Enberg bool ret = true; 227d4b02a37SThomas Gleixner char *addr = data; 22846aa8d69SPekka Enberg 2294ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2302932c9ebSPekka Enberg 231c6a69c61SPekka Enberg offset = port - dev->iobase; 232c6a69c61SPekka Enberg 23346aa8d69SPekka Enberg switch (offset) { 234c59fa0c4SThomas Gleixner case UART_TX: 235d4b02a37SThomas Gleixner if (dev->lcr & UART_LCR_DLAB) { 236c59fa0c4SThomas Gleixner dev->dll = ioport__read8(data); 237d4b02a37SThomas Gleixner break; 238d4b02a37SThomas Gleixner } 239d4b02a37SThomas Gleixner 240d4b02a37SThomas Gleixner /* Loopback mode */ 241d4b02a37SThomas Gleixner if (dev->mcr & UART_MCR_LOOP) { 242d4b02a37SThomas Gleixner if (dev->rxcnt < FIFO_LEN) { 243d4b02a37SThomas Gleixner dev->rxbuf[dev->rxcnt++] = *addr; 244d4b02a37SThomas Gleixner dev->lsr |= UART_LSR_DR; 245d4b02a37SThomas Gleixner } 246d4b02a37SThomas Gleixner break; 247d4b02a37SThomas Gleixner } 248d4b02a37SThomas Gleixner 249d4b02a37SThomas Gleixner if (dev->txcnt < FIFO_LEN) { 250d4b02a37SThomas Gleixner dev->txbuf[dev->txcnt++] = *addr; 251d4b02a37SThomas Gleixner dev->lsr &= ~UART_LSR_TEMT; 252d4b02a37SThomas Gleixner if (dev->txcnt == FIFO_LEN / 2) 253d4b02a37SThomas Gleixner dev->lsr &= ~UART_LSR_THRE; 2544123ca55SMarc Zyngier serial8250_flush_tx(vcpu->kvm, dev); 255d4b02a37SThomas Gleixner } else { 256d4b02a37SThomas Gleixner /* Should never happpen */ 257d4b02a37SThomas Gleixner dev->lsr &= ~(UART_LSR_TEMT | UART_LSR_THRE); 25846aa8d69SPekka Enberg } 259369c01c0SPekka Enberg break; 2604e49b05bSCyrill Gorcunov case UART_IER: 261f6b8ccc1SThomas Gleixner if (!(dev->lcr & UART_LCR_DLAB)) 262d4b02a37SThomas Gleixner dev->ier = ioport__read8(data) & 0x0f; 263f6b8ccc1SThomas Gleixner else 264c59fa0c4SThomas Gleixner dev->dlm = ioport__read8(data); 265c59fa0c4SThomas Gleixner break; 266c59fa0c4SThomas Gleixner case UART_FCR: 267c59fa0c4SThomas Gleixner dev->fcr = ioport__read8(data); 26846aa8d69SPekka Enberg break; 269369c01c0SPekka Enberg case UART_LCR: 270369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 271369c01c0SPekka Enberg break; 272369c01c0SPekka Enberg case UART_MCR: 273369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 274369c01c0SPekka Enberg break; 275369c01c0SPekka Enberg case UART_LSR: 276369c01c0SPekka Enberg /* Factory test */ 277369c01c0SPekka Enberg break; 278369c01c0SPekka Enberg case UART_MSR: 279369c01c0SPekka Enberg /* Not used */ 280369c01c0SPekka Enberg break; 281369c01c0SPekka Enberg case UART_SCR: 282369c01c0SPekka Enberg dev->scr = ioport__read8(data); 283369c01c0SPekka Enberg break; 284369c01c0SPekka Enberg default: 2852932c9ebSPekka Enberg ret = false; 286d2ea115dSThomas Gleixner break; 28746aa8d69SPekka Enberg } 2882932c9ebSPekka Enberg 2894123ca55SMarc Zyngier serial8250_update_irq(vcpu->kvm, dev); 290f6b8ccc1SThomas Gleixner 2914ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2922932c9ebSPekka Enberg 2932932c9ebSPekka Enberg return ret; 29413a7760fSPekka Enberg } 29513a7760fSPekka Enberg 296d4b02a37SThomas Gleixner static void serial8250_rx(struct serial8250_device *dev, void *data) 297d4b02a37SThomas Gleixner { 298d4b02a37SThomas Gleixner if (dev->rxdone == dev->rxcnt) 299d4b02a37SThomas Gleixner return; 300d4b02a37SThomas Gleixner 301d4b02a37SThomas Gleixner /* Break issued ? */ 302d4b02a37SThomas Gleixner if (dev->lsr & UART_LSR_BI) { 303d4b02a37SThomas Gleixner dev->lsr &= ~UART_LSR_BI; 304d4b02a37SThomas Gleixner ioport__write8(data, 0); 305d4b02a37SThomas Gleixner return; 306d4b02a37SThomas Gleixner } 307d4b02a37SThomas Gleixner 308d4b02a37SThomas Gleixner ioport__write8(data, dev->rxbuf[dev->rxdone++]); 309d4b02a37SThomas Gleixner if (dev->rxcnt == dev->rxdone) { 310d4b02a37SThomas Gleixner dev->lsr &= ~UART_LSR_DR; 311d4b02a37SThomas Gleixner dev->rxcnt = dev->rxdone = 0; 312d4b02a37SThomas Gleixner } 313d4b02a37SThomas Gleixner } 314d4b02a37SThomas Gleixner 3154123ca55SMarc Zyngier static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size) 31625af6674SPekka Enberg { 317d28abb58SWill Deacon struct serial8250_device *dev = ioport->priv; 3183fdf659dSSasha Levin u16 offset; 3192932c9ebSPekka Enberg bool ret = true; 32046aa8d69SPekka Enberg 3214ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 3222932c9ebSPekka Enberg 323c6a69c61SPekka Enberg offset = port - dev->iobase; 324c6a69c61SPekka Enberg 32546aa8d69SPekka Enberg switch (offset) { 326251cf9a6SPekka Enberg case UART_RX: 327d4b02a37SThomas Gleixner if (dev->lcr & UART_LCR_DLAB) 328c59fa0c4SThomas Gleixner ioport__write8(data, dev->dll); 329d4b02a37SThomas Gleixner else 330d4b02a37SThomas Gleixner serial8250_rx(dev, data); 331369c01c0SPekka Enberg break; 332c59fa0c4SThomas Gleixner case UART_IER: 333c59fa0c4SThomas Gleixner if (dev->lcr & UART_LCR_DLAB) 334c59fa0c4SThomas Gleixner ioport__write8(data, dev->dlm); 335c59fa0c4SThomas Gleixner else 336c59fa0c4SThomas Gleixner ioport__write8(data, dev->ier); 337c59fa0c4SThomas Gleixner break; 338f6b8ccc1SThomas Gleixner case UART_IIR: 339d4b02a37SThomas Gleixner ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS); 34046aa8d69SPekka Enberg break; 3414e49b05bSCyrill Gorcunov case UART_LCR: 342c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 34346aa8d69SPekka Enberg break; 3444e49b05bSCyrill Gorcunov case UART_MCR: 345c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 34646aa8d69SPekka Enberg break; 3474e49b05bSCyrill Gorcunov case UART_LSR: 348c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 34946aa8d69SPekka Enberg break; 3504e49b05bSCyrill Gorcunov case UART_MSR: 351369c01c0SPekka Enberg ioport__write8(data, dev->msr); 35246aa8d69SPekka Enberg break; 3534e49b05bSCyrill Gorcunov case UART_SCR: 354369c01c0SPekka Enberg ioport__write8(data, dev->scr); 35546aa8d69SPekka Enberg break; 356369c01c0SPekka Enberg default: 3572932c9ebSPekka Enberg ret = false; 358c59fa0c4SThomas Gleixner break; 35925af6674SPekka Enberg } 360f6b8ccc1SThomas Gleixner 3614123ca55SMarc Zyngier serial8250_update_irq(vcpu->kvm, dev); 362f6b8ccc1SThomas Gleixner 3634ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 3642932c9ebSPekka Enberg 3652932c9ebSPekka Enberg return ret; 36613a7760fSPekka Enberg } 36713a7760fSPekka Enberg 368d28abb58SWill Deacon #ifdef CONFIG_HAS_LIBFDT 369e5965f36SMarc Zyngier #define DEVICE_NAME_MAX_LEN 32 370*2bfd9ac3SAndre Przywara static 371*2bfd9ac3SAndre Przywara void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt, 372d28abb58SWill Deacon void (*generate_irq_prop)(void *fdt, 373*2bfd9ac3SAndre Przywara u8 irq, 374*2bfd9ac3SAndre Przywara enum irq_type)) 375d28abb58SWill Deacon { 376e5965f36SMarc Zyngier char dev_name[DEVICE_NAME_MAX_LEN]; 377d28abb58SWill Deacon struct serial8250_device *dev = ioport->priv; 378e5965f36SMarc Zyngier u64 addr = KVM_IOPORT_AREA + dev->iobase; 379d28abb58SWill Deacon u64 reg_prop[] = { 380e5965f36SMarc Zyngier cpu_to_fdt64(addr), 381d28abb58SWill Deacon cpu_to_fdt64(8), 382d28abb58SWill Deacon }; 383d28abb58SWill Deacon 384e5965f36SMarc Zyngier snprintf(dev_name, DEVICE_NAME_MAX_LEN, "U6_16550A@%llx", addr); 385e5965f36SMarc Zyngier 386e5965f36SMarc Zyngier _FDT(fdt_begin_node(fdt, dev_name)); 387d28abb58SWill Deacon _FDT(fdt_property_string(fdt, "compatible", "ns16550a")); 388d28abb58SWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 389*2bfd9ac3SAndre Przywara generate_irq_prop(fdt, dev->irq, IRQ_TYPE_EDGE_RISING); 390d28abb58SWill Deacon _FDT(fdt_property_cell(fdt, "clock-frequency", 1843200)); 391d28abb58SWill Deacon _FDT(fdt_end_node(fdt)); 392d28abb58SWill Deacon } 393d28abb58SWill Deacon #else 394d28abb58SWill Deacon #define serial8250_generate_fdt_node NULL 395d28abb58SWill Deacon #endif 396d28abb58SWill Deacon 39746aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 39846aa8d69SPekka Enberg .io_in = serial8250_in, 39946aa8d69SPekka Enberg .io_out = serial8250_out, 400d28abb58SWill Deacon .generate_fdt_node = serial8250_generate_fdt_node, 401a93ec68bSPekka Enberg }; 402a93ec68bSPekka Enberg 40320715a22SSasha Levin static int serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 404bc4b0ffeSPekka Enberg { 40520715a22SSasha Levin int r; 40620715a22SSasha Levin 407206c41f4SWill Deacon ioport__map_irq(&dev->irq); 408d28abb58SWill Deacon r = ioport__register(kvm, dev->iobase, &serial8250_ops, 8, dev); 409bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 41020715a22SSasha Levin 41120715a22SSasha Levin return r; 412bc4b0ffeSPekka Enberg } 413bc4b0ffeSPekka Enberg 41420715a22SSasha Levin int serial8250__init(struct kvm *kvm) 41513a7760fSPekka Enberg { 41620715a22SSasha Levin unsigned int i, j; 41720715a22SSasha Levin int r = 0; 418c6a69c61SPekka Enberg 419c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 420c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 421c6a69c61SPekka Enberg 42220715a22SSasha Levin r = serial8250__device_init(kvm, dev); 42320715a22SSasha Levin if (r < 0) 42420715a22SSasha Levin goto cleanup; 425c6a69c61SPekka Enberg } 42620715a22SSasha Levin 42720715a22SSasha Levin return r; 42820715a22SSasha Levin cleanup: 42920715a22SSasha Levin for (j = 0; j <= i; j++) { 43020715a22SSasha Levin struct serial8250_device *dev = &devices[j]; 43120715a22SSasha Levin 4324346fd8fSSasha Levin ioport__unregister(kvm, dev->iobase); 43320715a22SSasha Levin } 43420715a22SSasha Levin 43520715a22SSasha Levin return r; 43620715a22SSasha Levin } 43749a8afd1SSasha Levin dev_init(serial8250__init); 43820715a22SSasha Levin 43920715a22SSasha Levin int serial8250__exit(struct kvm *kvm) 44020715a22SSasha Levin { 44120715a22SSasha Levin unsigned int i; 44220715a22SSasha Levin int r; 44320715a22SSasha Levin 44420715a22SSasha Levin for (i = 0; i < ARRAY_SIZE(devices); i++) { 44520715a22SSasha Levin struct serial8250_device *dev = &devices[i]; 44620715a22SSasha Levin 4474346fd8fSSasha Levin r = ioport__unregister(kvm, dev->iobase); 44820715a22SSasha Levin if (r < 0) 44920715a22SSasha Levin return r; 45020715a22SSasha Levin } 45120715a22SSasha Levin 45220715a22SSasha Levin return 0; 45313a7760fSPekka Enberg } 45449a8afd1SSasha Levin dev_exit(serial8250__exit); 455