^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * dz.c: Serial port driver for DECstations equipped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * with the DZ chipset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1998 Olivier A. D. Lebaillif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Email: olivier.lebaillif@ifrsys.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2004, 2006, 2007 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * [31-AUG-98] triemer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Changed IRQ to use Harald's dec internals interrupts.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * removed base_addr code - moving address assignment to setup.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Changed name of dz_init to rs_init to be consistent with tc code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * [13-NOV-98] triemer fixed code to receive characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * after patches by harald to irq code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * field from "current" - somewhere between 2.1.121 and 2.1.131
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) Qua Jun 27 15:02:26 BRT 2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Parts (C) 1999 David Airlie, airlied@linux.ie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * [07-SEP-99] Bugfixes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Converted to new serial core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #undef DEBUG_DZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <asm/dec/interrupts.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/dec/kn01.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/dec/kn02.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/dec/machtype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <asm/dec/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <asm/dec/system.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include "dz.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) MODULE_DESCRIPTION("DECstation DZ serial driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static char dz_name[] __initdata = "DECstation DZ serial driver version ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static char dz_version[] __initdata = "1.04";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct dz_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct dz_mux *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct uart_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct dz_mux {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct dz_port dport[DZ_NB_PORT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) atomic_t map_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) atomic_t irq_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int initialised;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static struct dz_mux dz_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline struct dz_port *to_dport(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return container_of(uport, struct dz_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * dz_in () and dz_out ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * These routines are used to access the registers of the DZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * chip, hiding relocation differences between implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static u16 dz_in(struct dz_port *dport, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void __iomem *addr = dport->port.membase + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return readw(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void dz_out(struct dz_port *dport, unsigned offset, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) void __iomem *addr = dport->port.membase + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writew(value, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * rs_stop () and rs_start ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * These routines are called before setting or resetting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * tty->stopped. They enable or disable transmitter interrupts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * as necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void dz_stop_tx(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u16 tmp, mask = 1 << dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) tmp &= ~mask; /* clear the TX flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dz_out(dport, DZ_TCR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void dz_start_tx(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u16 tmp, mask = 1 << dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) tmp |= mask; /* set the TX flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dz_out(dport, DZ_TCR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void dz_stop_rx(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dport->cflag &= ~DZ_RXENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dz_out(dport, DZ_LPR, dport->cflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Here start the interrupt handling routines. All of the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * subroutines are declared as inline and are folded into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * dz_interrupt. They were separated out for readability's sake.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * Note: dz_interrupt() is a "fast" interrupt, which means that it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * runs with interrupts turned off. People who may want to modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * dz_interrupt() should try to keep the interrupt handler as fast as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * possible. After you are done making modifications, it is not a bad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * idea to do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * make drivers/serial/dz.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * and look at the resulting assemble code in dz.s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * receive_char ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * This routine deals with inputs from any lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static inline void dz_receive_chars(struct dz_mux *mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct uart_port *uport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct dz_port *dport = &mux->dport[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct uart_icount *icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned char ch, flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dport = &mux->dport[LINE(status)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) uport = &dport->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ch = UCHAR(status); /* grab the char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) icount = &uport->icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) icount->rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * There is no separate BREAK status bit, so treat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * null characters with framing errors as BREAKs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * normally, otherwise. For this move the Framing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Error bit to a simulated BREAK bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) status |= (status & DZ_FERR) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (ffs(DZ_FERR) - ffs(DZ_BREAK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) status &= ~DZ_FERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Handle SysRq/SAK & keep track of the statistics. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (status & DZ_BREAK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) icount->brk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (uart_handle_break(uport))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) } else if (status & DZ_FERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) icount->frame++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) else if (status & DZ_PERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) icount->parity++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (status & DZ_OERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) icount->overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) status &= uport->read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (status & DZ_BREAK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) flag = TTY_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) else if (status & DZ_FERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) flag = TTY_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) else if (status & DZ_PERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (uart_handle_sysrq_char(uport, ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) uart_insert_char(uport, status, DZ_OERR, ch, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) lines_rx[LINE(status)] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) for (i = 0; i < DZ_NB_PORT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (lines_rx[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) tty_flip_buffer_push(&mux->dport[i].port.state->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * transmit_char ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * This routine deals with outputs to any lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static inline void dz_transmit_chars(struct dz_mux *mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct dz_port *dport = &mux->dport[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct circ_buf *xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) unsigned char tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) status = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) dport = &mux->dport[LINE(status)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) xmit = &dport->port.state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (dport->port.x_char) { /* XON/XOFF chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dz_out(dport, DZ_TDR, dport->port.x_char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) dport->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dport->port.x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* If nothing to do or stopped or hardware stopped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) spin_lock(&dport->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dz_stop_tx(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) spin_unlock(&dport->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * If something to do... (remember the dz has no output fifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * so we go one char at a time) :-<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tmp = xmit->buf[xmit->tail];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) dz_out(dport, DZ_TDR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dport->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) uart_write_wakeup(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* Are we are done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (uart_circ_empty(xmit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) spin_lock(&dport->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dz_stop_tx(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) spin_unlock(&dport->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * check_modem_status()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * DS 3100 & 5100: Only valid for the MODEM line, duh!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * DS 5000/200: Valid for the MODEM and PRINTER line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static inline void check_modem_status(struct dz_port *dport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * FIXME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * 1. No status change interrupt; use a timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * 2. Handle the 3100/5000 as appropriate. --macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* If not the modem line just return. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (dport->port.line != DZ_MODEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) status = dz_in(dport, DZ_MSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* it's easy, since DSR2 is the only bit in the register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dport->port.icount.dsr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * dz_interrupt ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * this is the main interrupt routine for the DZ chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * It deals with the multiple ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * ------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static irqreturn_t dz_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct dz_mux *mux = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct dz_port *dport = &mux->dport[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* get the reason why we just got an irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) status = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) dz_receive_chars(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) dz_transmit_chars(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Here ends the DZ interrupt routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static unsigned int dz_get_mctrl(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * FIXME: Handle the 3100/5000 as appropriate. --macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (dport->port.line == DZ_MODEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) mctrl &= ~TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * FIXME: Handle the 3100/5000 as appropriate. --macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (dport->port.line == DZ_MODEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) tmp = dz_in(dport, DZ_TCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (mctrl & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) tmp &= ~DZ_MODEM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) tmp |= DZ_MODEM_DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dz_out(dport, DZ_TCR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * startup ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * various initialization tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int dz_startup(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct dz_mux *mux = dport->mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int irq_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) irq_guard = atomic_add_return(1, &mux->irq_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (irq_guard != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret = request_irq(dport->port.irq, dz_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) IRQF_SHARED, "dz", mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) atomic_add(-1, &mux->irq_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) spin_lock_irqsave(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* Enable interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) tmp = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) tmp |= DZ_RIE | DZ_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) dz_out(dport, DZ_CSR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) spin_unlock_irqrestore(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * shutdown ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * This routine will shutdown a serial port; interrupts are disabled, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * DTR is dropped if the hangup on close termio flag is on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void dz_shutdown(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct dz_mux *mux = dport->mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int irq_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) spin_lock_irqsave(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dz_stop_tx(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) spin_unlock_irqrestore(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) irq_guard = atomic_add_return(-1, &mux->irq_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!irq_guard) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* Disable interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) tmp = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) tmp &= ~(DZ_RIE | DZ_TIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) dz_out(dport, DZ_CSR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) free_irq(dport->port.irq, mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * dz_tx_empty() -- get the transmitter empty status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * Purpose: Let user call ioctl() to get info when the UART physically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * is emptied. On bus types like RS485, the transmitter must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * release the bus after transmitting. This must be done when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * the transmit shift register is empty, not be done when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * transmit holding register is empty. This functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * allows an RS485 driver to be written in user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static unsigned int dz_tx_empty(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unsigned short tmp, mask = 1 << dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) tmp = dz_in(dport, DZ_TCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) tmp &= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return tmp ? 0 : TIOCSER_TEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static void dz_break_ctl(struct uart_port *uport, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * FIXME: Can't access BREAK bits in TDR easily;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * reuse the code for polled TX. --macro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) unsigned short tmp, mask = 1 << dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) spin_lock_irqsave(&uport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) tmp = dz_in(dport, DZ_TCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) tmp |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) tmp &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dz_out(dport, DZ_TCR, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) spin_unlock_irqrestore(&uport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int dz_encode_baud_rate(unsigned int baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) switch (baud) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case 50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return DZ_B50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case 75:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return DZ_B75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case 110:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return DZ_B110;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case 134:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return DZ_B134;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case 150:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return DZ_B150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case 300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return DZ_B300;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case 600:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return DZ_B600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case 1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return DZ_B1200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case 1800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return DZ_B1800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) case 2000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return DZ_B2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case 2400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return DZ_B2400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case 3600:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return DZ_B3600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case 4800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return DZ_B4800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case 7200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return DZ_B7200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case 9600:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return DZ_B9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static void dz_reset(struct dz_port *dport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct dz_mux *mux = dport->mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (mux->initialised)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) dz_out(dport, DZ_CSR, DZ_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) while (dz_in(dport, DZ_CSR) & DZ_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* Enable scanning. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) dz_out(dport, DZ_CSR, DZ_MSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mux->initialised = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct ktermios *old_termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) unsigned int cflag, baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int bflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) cflag = dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) switch (termios->c_cflag & CSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) case CS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) cflag |= DZ_CS5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case CS6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) cflag |= DZ_CS6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case CS7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) cflag |= DZ_CS7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case CS8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) cflag |= DZ_CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (termios->c_cflag & CSTOPB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) cflag |= DZ_CSTOPB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (termios->c_cflag & PARENB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) cflag |= DZ_PARENB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (termios->c_cflag & PARODD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) cflag |= DZ_PARODD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) bflag = dz_encode_baud_rate(baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (bflag < 0) { /* Try to keep unchanged. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) baud = uart_get_baud_rate(uport, old_termios, NULL, 50, 9600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) bflag = dz_encode_baud_rate(baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (bflag < 0) { /* Resort to 9600. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) baud = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) bflag = DZ_B9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) tty_termios_encode_baud_rate(termios, baud, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cflag |= bflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (termios->c_cflag & CREAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) cflag |= DZ_RXENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) spin_lock_irqsave(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) uart_update_timeout(uport, termios->c_cflag, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dz_out(dport, DZ_LPR, cflag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) dport->cflag = cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* setup accept flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dport->port.read_status_mask = DZ_OERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (termios->c_iflag & INPCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) dport->port.read_status_mask |= DZ_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* characters to ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) uport->ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dport->port.ignore_status_mask |= DZ_OERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (termios->c_iflag & IGNBRK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) dport->port.ignore_status_mask |= DZ_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) spin_unlock_irqrestore(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * Hack alert!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Required solely so that the initial PROM-based console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * works undisturbed in parallel with this one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static void dz_pm(struct uart_port *uport, unsigned int state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) unsigned int oldstate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) spin_lock_irqsave(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (state < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dz_start_tx(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) dz_stop_tx(&dport->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) spin_unlock_irqrestore(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static const char *dz_type(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return "DZ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static void dz_release_port(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct dz_mux *mux = to_dport(uport)->mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int map_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) iounmap(uport->membase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) uport->membase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) map_guard = atomic_add_return(-1, &mux->map_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (!map_guard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) release_mem_region(uport->mapbase, dec_kn_slot_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static int dz_map_port(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!uport->membase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) uport->membase = ioremap(uport->mapbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dec_kn_slot_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (!uport->membase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) printk(KERN_ERR "dz: Cannot map MMIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int dz_request_port(struct uart_port *uport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct dz_mux *mux = to_dport(uport)->mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int map_guard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) map_guard = atomic_add_return(1, &mux->map_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (map_guard == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!request_mem_region(uport->mapbase, dec_kn_slot_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) "dz")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) atomic_add(-1, &mux->map_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) "dz: Unable to reserve MMIO resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = dz_map_port(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) map_guard = atomic_add_return(-1, &mux->map_guard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (!map_guard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) release_mem_region(uport->mapbase, dec_kn_slot_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static void dz_config_port(struct uart_port *uport, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (flags & UART_CONFIG_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (dz_request_port(uport))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) uport->type = PORT_DZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) dz_reset(dport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * Verify the new serial_struct (for TIOCSSERIAL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ser->irq != uport->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static const struct uart_ops dz_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .tx_empty = dz_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .get_mctrl = dz_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .set_mctrl = dz_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .stop_tx = dz_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .start_tx = dz_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) .stop_rx = dz_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) .break_ctl = dz_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .startup = dz_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) .shutdown = dz_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .set_termios = dz_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .pm = dz_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .type = dz_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .release_port = dz_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .request_port = dz_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .config_port = dz_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .verify_port = dz_verify_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static void __init dz_init_ports(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static int first = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) first = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) base = dec_kn_slot_base + KN01_DZ11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) base = dec_kn_slot_base + KN02_DZ11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) for (line = 0; line < DZ_NB_PORT; line++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct dz_port *dport = &dz_mux.dport[line];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct uart_port *uport = &dport->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) dport->mux = &dz_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) uport->irq = dec_interrupt[DEC_IRQ_DZ11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) uport->fifosize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) uport->iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) uport->flags = UPF_BOOT_AUTOCONF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) uport->ops = &dz_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) uport->line = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) uport->mapbase = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_DZ_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) #ifdef CONFIG_SERIAL_DZ_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * dz_console_putchar() -- transmit a character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * Polled transmission. This is tricky. We need to mask transmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * interrupts so that they do not interfere, enable the transmitter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * for the line requested and then wait till the transmit scanner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * requests data for this line. But it may request data for another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * line first, in which case we have to disable its transmitter and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * repeat waiting till our line pops up. Only then the character may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * be transmitted. Finally, the state of the transmitter mask is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * restored. Welcome to the world of PDP-11!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static void dz_console_putchar(struct uart_port *uport, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct dz_port *dport = to_dport(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) unsigned short csr, tcr, trdy, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int loops = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) spin_lock_irqsave(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) csr = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dz_out(dport, DZ_CSR, csr & ~DZ_TIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) tcr = dz_in(dport, DZ_TCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) tcr |= 1 << dport->port.line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mask = tcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) dz_out(dport, DZ_TCR, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) spin_unlock_irqrestore(&dport->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) trdy = dz_in(dport, DZ_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (!(trdy & DZ_TRDY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) trdy = (trdy & DZ_TLINE) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (trdy == dport->port.line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) mask &= ~(1 << trdy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) dz_out(dport, DZ_TCR, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) } while (--loops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (loops) /* Cannot send otherwise. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dz_out(dport, DZ_TDR, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) dz_out(dport, DZ_TCR, tcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) dz_out(dport, DZ_CSR, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * dz_console_print ()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * dz_console_print is registered for printk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * The console must be locked when we get here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * -------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static void dz_console_print(struct console *co,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct dz_port *dport = &dz_mux.dport[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) #ifdef DEBUG_DZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) prom_printf((char *) str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) uart_console_write(&dport->port, str, count, dz_console_putchar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int __init dz_console_setup(struct console *co, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct dz_port *dport = &dz_mux.dport[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct uart_port *uport = &dport->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) int baud = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) int bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int flow = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = dz_map_port(uport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) spin_lock_init(&dport->port.lock); /* For dz_pm(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dz_reset(dport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) dz_pm(uport, 0, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) uart_parse_options(options, &baud, &parity, &bits, &flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return uart_set_options(&dport->port, co, baud, parity, bits, flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static struct uart_driver dz_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) static struct console dz_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .write = dz_console_print,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) .device = uart_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .setup = dz_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) .data = &dz_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static int __init dz_serial_console_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (!IOASIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) dz_init_ports();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) register_console(&dz_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) console_initcall(dz_serial_console_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) #define SERIAL_DZ_CONSOLE &dz_console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) #define SERIAL_DZ_CONSOLE NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) #endif /* CONFIG_SERIAL_DZ_CONSOLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static struct uart_driver dz_reg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .driver_name = "serial",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .dev_name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .major = TTY_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .minor = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .nr = DZ_NB_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .cons = SERIAL_DZ_CONSOLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int __init dz_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (IOASIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) printk("%s%s\n", dz_name, dz_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dz_init_ports();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ret = uart_register_driver(&dz_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) for (i = 0; i < DZ_NB_PORT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) uart_add_one_port(&dz_reg, &dz_mux.dport[i].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) module_init(dz_init);