^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) /* sunzilog.c: Zilog serial driver for Sparc systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Driver for Zilog serial chips found on Sun workstations and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * servers. This driver could actually be made more generic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This is based on the old drivers/sbus/char/zs.c code. A lot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * of code has been simply moved over directly from there but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * much has been rewritten. Credits therefore go out to Eddie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * work there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/circ_buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/sunserialcore.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include "sunzilog.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* On 32-bit sparcs we need to delay after register accesses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * to accommodate sun4 systems, but we do not need to flush writes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * On 64-bit sparc we only need to flush single writes to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifndef CONFIG_SPARC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define ZSDELAY() udelay(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ZSDELAY_LONG() udelay(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ZS_WSYNC(channel) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ZSDELAY()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ZSDELAY_LONG()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define ZS_WSYNC(__channel) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) readb(&((__channel)->control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define ZS_CLOCK 4915200 /* Zilog input clock rate. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * We wrap our port structure around the generic uart_port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct uart_sunzilog_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct uart_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* IRQ servicing chain. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct uart_sunzilog_port *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Current values of Zilog write registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned char curregs[NUM_ZSREGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define SUNZILOG_FLAG_CONS_KEYB 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define SUNZILOG_FLAG_CONS_MOUSE 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SUNZILOG_FLAG_IS_CONS 0x00000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SUNZILOG_FLAG_IS_KGDB 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SUNZILOG_FLAG_MODEM_STATUS 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SUNZILOG_FLAG_IS_CHANNEL_A 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define SUNZILOG_FLAG_REGS_HELD 0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SUNZILOG_FLAG_TX_STOPPED 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SUNZILOG_FLAG_ESCC 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SUNZILOG_FLAG_ISR_HANDLER 0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned int cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned char parity_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned char prev_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct serio serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int serio_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void sunzilog_putchar(struct uart_port *port, int ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel __iomem *)((PORT)->membase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define UART_ZILOG(PORT) ((struct uart_sunzilog_port *)(PORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define ZS_IS_KEYB(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_KEYB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define ZS_IS_MOUSE(UP) ((UP)->flags & SUNZILOG_FLAG_CONS_MOUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define ZS_IS_CONS(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CONS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define ZS_IS_KGDB(UP) ((UP)->flags & SUNZILOG_FLAG_IS_KGDB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & SUNZILOG_FLAG_MODEM_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define ZS_IS_CHANNEL_A(UP) ((UP)->flags & SUNZILOG_FLAG_IS_CHANNEL_A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define ZS_REGS_HELD(UP) ((UP)->flags & SUNZILOG_FLAG_REGS_HELD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define ZS_TX_STOPPED(UP) ((UP)->flags & SUNZILOG_FLAG_TX_STOPPED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define ZS_TX_ACTIVE(UP) ((UP)->flags & SUNZILOG_FLAG_TX_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Reading and writing Zilog8530 registers. The delays are to make this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * driver work on the Sun4 which needs a settling delay after each chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * register access, other machines handle this in hardware via auxiliary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * flip-flops which implement the settle time we do in software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * The port lock must be held and local IRQs must be disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * when {read,write}_zsreg is invoked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned char reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned char retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) writeb(reg, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) retval = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void write_zsreg(struct zilog_channel __iomem *channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned char reg, unsigned char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) writeb(reg, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) writeb(value, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned char regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) regval = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (regval & Rx_CH_AV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) regval = read_zsreg(channel, R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) readb(&channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) writeb(ERR_RES, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ZS_WSYNC(channel);
^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) /* This function must only be called when the TX is not busy. The UART
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * port lock must be held and local interrupts disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int escc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned char r15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Let pending transmits finish. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (i = 0; i < 1000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned char stat = read_zsreg(channel, R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (stat & ALL_SNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) writeb(ERR_RES, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) sunzilog_clear_fifo(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Disable all interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) write_zsreg(channel, R1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* Set parity, sync config, stop bits, and clock divisor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) write_zsreg(channel, R4, regs[R4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Set misc. TX/RX control bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) write_zsreg(channel, R10, regs[R10]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Set TX/RX controls sans the enable bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) write_zsreg(channel, R3, regs[R3] & ~RxENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) write_zsreg(channel, R5, regs[R5] & ~TxENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Synchronous mode config. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) write_zsreg(channel, R6, regs[R6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) write_zsreg(channel, R7, regs[R7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Don't mess with the interrupt vector (R2, unused by us) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * master interrupt control (R9). We make sure this is setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * properly at probe time then never touch it again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* Disable baud generator. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) write_zsreg(channel, R14, regs[R14] & ~BRENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* Clock mode control. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) write_zsreg(channel, R11, regs[R11]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Lower and upper byte of baud rate generator divisor. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) write_zsreg(channel, R12, regs[R12]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) write_zsreg(channel, R13, regs[R13]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Now rewrite R14, with BRENAB (if set). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) write_zsreg(channel, R14, regs[R14]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* External status interrupt control. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* ESCC Extension Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) r15 = read_zsreg(channel, R15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (r15 & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) write_zsreg(channel, R7, regs[R7p]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* External status interrupt and FIFO control. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) write_zsreg(channel, R15, regs[R15] & ~WR7pEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) escc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Clear FIFO bit case it is an issue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) regs[R15] &= ~FIFOEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) escc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* Reset external status interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Rewrite R3/R5, this time without enables masked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) write_zsreg(channel, R3, regs[R3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) write_zsreg(channel, R5, regs[R5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Rewrite R1, this time without IRQ enabled masked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) write_zsreg(channel, R1, regs[R1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return escc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Reprogram the Zilog channel HW registers with the copies found in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * software state struct. If the transmitter is busy, we defer this update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * until the next TX complete interrupt. Else, we do it right now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * The UART port lock must be held and local interrupts disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static void sunzilog_maybe_update_regs(struct uart_sunzilog_port *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct zilog_channel __iomem *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!ZS_REGS_HELD(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (ZS_TX_ACTIVE(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) up->flags |= SUNZILOG_FLAG_REGS_HELD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) __load_zsregs(channel, up->curregs);
^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) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static void sunzilog_change_mouse_baud(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) unsigned int cur_cflag = up->cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int brg, new_baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) up->cflag &= ~CBAUD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) up->cflag |= suncore_mouse_baud_cflag_next(cur_cflag, &new_baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) brg = BPS_TO_BRG(new_baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) up->curregs[R12] = (brg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) up->curregs[R13] = (brg >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(&up->port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) unsigned char ch, int is_break)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ZS_IS_KEYB(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Stop-A is handled by drivers/char/keyboard.c now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (up->serio_open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) serio_interrupt(&up->serio, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) } else if (ZS_IS_MOUSE(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int ret = suncore_mouse_baud_detection(ch, is_break);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sunzilog_change_mouse_baud(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (up->serio_open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) serio_interrupt(&up->serio, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static struct tty_port *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sunzilog_receive_chars(struct uart_sunzilog_port *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct zilog_channel __iomem *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct tty_port *port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) unsigned char ch, r1, flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (up->port.state != NULL) /* Unopened serial console */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) port = &up->port.state->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) r1 = read_zsreg(channel, R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) writeb(ERR_RES, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ch = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* This funny hack depends upon BRK_ABRT not interfering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * with the other bits we care about in R1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (ch & BRK_ABRT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) r1 |= BRK_ABRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!(ch & Rx_CH_AV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ch = readb(&channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ch &= up->parity_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (unlikely(ZS_IS_KEYB(up)) || unlikely(ZS_IS_MOUSE(up))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) sunzilog_kbdms_receive_chars(up, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* A real serial line, record the character and status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) up->port.icount.rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (r1 & BRK_ABRT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) r1 &= ~(PAR_ERR | CRC_ERR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) up->port.icount.brk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (uart_handle_break(&up->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) else if (r1 & PAR_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) up->port.icount.parity++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) else if (r1 & CRC_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) up->port.icount.frame++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (r1 & Rx_OVR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) up->port.icount.overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) r1 &= up->port.read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (r1 & BRK_ABRT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) flag = TTY_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) else if (r1 & PAR_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) else if (r1 & CRC_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) flag = TTY_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (uart_handle_sysrq_char(&up->port, ch) || !port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (up->port.ignore_status_mask == 0xff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) (r1 & up->port.ignore_status_mask) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) tty_insert_flip_char(port, ch, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (r1 & Rx_OVR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) tty_insert_flip_char(port, 0, TTY_OVERRUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static void sunzilog_status_handle(struct uart_sunzilog_port *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct zilog_channel __iomem *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) writeb(RES_EXT_INT, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (status & BRK_ABRT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (ZS_IS_MOUSE(up))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) sunzilog_kbdms_receive_chars(up, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (ZS_IS_CONS(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Wait for BREAK to deassert to avoid potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * confusing the PROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!(status & BRK_ABRT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) sun_do_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return;
^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) if (ZS_WANTS_MODEM_STATUS(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (status & SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) up->port.icount.dsr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* The Zilog just gives us an interrupt when DCD/CTS/etc. change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * But it does not tell us which bit has changed, we have to keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * track of this ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if ((status ^ up->prev_status) ^ DCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) uart_handle_dcd_change(&up->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) (status & DCD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if ((status ^ up->prev_status) ^ CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) uart_handle_cts_change(&up->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) (status & CTS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) wake_up_interruptible(&up->port.state->port.delta_msr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) up->prev_status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct zilog_channel __iomem *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct circ_buf *xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (ZS_IS_CONS(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) unsigned char status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* TX still busy? Just wait for the next TX done interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * It can occur because of how we do serial console writes. It would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * be nice to transmit console writes just like we normally would for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * a TTY line. (ie. buffered and TX interrupt driven). That is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * easy because console writes cannot sleep. One solution might be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * to poll on enough port->xmit space becoming free. -DaveM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!(status & Tx_BUF_EMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return;
^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) up->flags &= ~SUNZILOG_FLAG_TX_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (ZS_REGS_HELD(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) __load_zsregs(channel, up->curregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) up->flags &= ~SUNZILOG_FLAG_REGS_HELD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (ZS_TX_STOPPED(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) goto ack_tx_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (up->port.x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) writeb(up->port.x_char, &channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) up->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) up->port.x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (up->port.state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) goto ack_tx_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) xmit = &up->port.state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) goto ack_tx_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (uart_tx_stopped(&up->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) goto ack_tx_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) writeb(xmit->buf[xmit->tail], &channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) up->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) uart_write_wakeup(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ack_tx_int:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) writeb(RES_Tx_P, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static irqreturn_t sunzilog_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct uart_sunzilog_port *up = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) while (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct zilog_channel __iomem *channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct tty_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) unsigned char r3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) spin_lock(&up->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) r3 = read_zsreg(channel, R3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* Channel A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) writeb(RES_H_IUS, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (r3 & CHARxIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) port = sunzilog_receive_chars(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (r3 & CHAEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) sunzilog_status_handle(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (r3 & CHATxIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) sunzilog_transmit_chars(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) spin_unlock(&up->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) tty_flip_buffer_push(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Channel B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) up = up->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) spin_lock(&up->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) writeb(RES_H_IUS, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (r3 & CHBRxIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) port = sunzilog_receive_chars(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (r3 & CHBEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) sunzilog_status_handle(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (r3 & CHBTxIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) sunzilog_transmit_chars(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) spin_unlock(&up->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) tty_flip_buffer_push(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) up = up->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return IRQ_HANDLED;
^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) /* A convenient way to quickly get R0 status. The caller must _not_ hold the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * port lock, it is acquired here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* The port lock is not held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static unsigned int sunzilog_tx_empty(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) unsigned int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) status = sunzilog_read_channel_status(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (status & Tx_BUF_EMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ret = TIOCSER_TEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* The port lock is held and interrupts are disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static unsigned int sunzilog_get_mctrl(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) status = sunzilog_read_channel_status(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (status & DCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) ret |= TIOCM_CAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (status & SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ret |= TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (status & CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ret |= TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* The port lock is held and interrupts are disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) unsigned char set_bits, clear_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) set_bits = clear_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (mctrl & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) set_bits |= RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) clear_bits |= RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (mctrl & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) set_bits |= DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) clear_bits |= DTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* NOTE: Not subject to 'transmitter active' rule. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) up->curregs[R5] |= set_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) up->curregs[R5] &= ~clear_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) write_zsreg(channel, R5, up->curregs[R5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* The port lock is held and interrupts are disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static void sunzilog_stop_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) up->flags |= SUNZILOG_FLAG_TX_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* The port lock is held and interrupts are disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void sunzilog_start_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) up->flags |= SUNZILOG_FLAG_TX_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) up->flags &= ~SUNZILOG_FLAG_TX_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* TX busy? Just wait for the TX done interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (!(status & Tx_BUF_EMP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Send the first character to jump-start the TX done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * IRQ sending engine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (port->x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) writeb(port->x_char, &channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) port->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) port->x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct circ_buf *xmit = &port->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) writeb(xmit->buf[xmit->tail], &channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) port->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) uart_write_wakeup(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* The port lock is held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static void sunzilog_stop_rx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct uart_sunzilog_port *up = UART_ZILOG(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (ZS_IS_CONS(up))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* Disable all RX interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) up->curregs[R1] &= ~RxINT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) sunzilog_maybe_update_regs(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /* The port lock is held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static void sunzilog_enable_ms(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) unsigned char new_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (new_reg != up->curregs[R15]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) up->curregs[R15] = new_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* NOTE: Not subject to 'transmitter active' rule. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* The port lock is not held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static void sunzilog_break_ctl(struct uart_port *port, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned char set_bits, clear_bits, new_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) set_bits = clear_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) set_bits |= SND_BRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) clear_bits |= SND_BRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (new_reg != up->curregs[R5]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) up->curregs[R5] = new_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* NOTE: Not subject to 'transmitter active' rule. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) write_zsreg(channel, R5, up->curregs[R5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static void __sunzilog_startup(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) up->prev_status = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* Enable receiver and transmitter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) up->curregs[R3] |= RxENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) up->curregs[R5] |= TxENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) sunzilog_maybe_update_regs(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int sunzilog_startup(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct uart_sunzilog_port *up = UART_ZILOG(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (ZS_IS_CONS(up))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) __sunzilog_startup(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * The test for ZS_IS_CONS is explained by the following e-mail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) *****
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * From: Russell King <rmk@arm.linux.org.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * Date: Sun, 8 Dec 2002 10:18:38 +0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * > I boot my 2.5 boxes using "console=ttyS0,9600" argument,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * > and I noticed that something is not right with reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * > counting in this case. It seems that when the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * > is open by kernel initially, this is not accounted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * > as an open, and uart_startup is not called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * That is correct. We are unable to call uart_startup when the serial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * console is initialised because it may need to allocate memory (as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * request_irq does) and the memory allocators may not have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * initialised.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * 1. initialise the port into a state where it can send characters in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * console write method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * 2. don't do the actual hardware shutdown in your shutdown() method (but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * do the normal software shutdown - ie, free irqs etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) *****
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static void sunzilog_shutdown(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct uart_sunzilog_port *up = UART_ZILOG(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (ZS_IS_CONS(up))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* Disable receiver and transmitter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) up->curregs[R3] &= ~RxENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) up->curregs[R5] &= ~TxENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /* Disable all interrupts and BRK assertion. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) up->curregs[R5] &= ~SND_BRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) sunzilog_maybe_update_regs(up, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) spin_unlock_irqrestore(&port->lock, flags);
^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) /* Shared by TTY driver and serial console setup. The port lock is held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * and local interrupts are disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) unsigned int iflag, int brg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) up->curregs[R10] = NRZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) up->curregs[R11] = TCBR | RCBR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* Program BAUD and clock source. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) up->curregs[R4] &= ~XCLK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) up->curregs[R4] |= X16CLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) up->curregs[R12] = brg & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) up->curregs[R13] = (brg >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) up->curregs[R14] = BRSRC | BRENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* Character size, stop bits, and parity. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) up->curregs[R3] &= ~RxN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) up->curregs[R5] &= ~TxN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) switch (cflag & CSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case CS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) up->curregs[R3] |= Rx5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) up->curregs[R5] |= Tx5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) up->parity_mask = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) case CS6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) up->curregs[R3] |= Rx6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) up->curregs[R5] |= Tx6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) up->parity_mask = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case CS7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) up->curregs[R3] |= Rx7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) up->curregs[R5] |= Tx7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) up->parity_mask = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) case CS8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) up->curregs[R3] |= Rx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) up->curregs[R5] |= Tx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) up->parity_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) up->curregs[R4] &= ~0x0c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (cflag & CSTOPB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) up->curregs[R4] |= SB2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) up->curregs[R4] |= SB1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (cflag & PARENB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) up->curregs[R4] |= PAR_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) up->curregs[R4] &= ~PAR_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!(cflag & PARODD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) up->curregs[R4] |= PAR_EVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) up->curregs[R4] &= ~PAR_EVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) up->port.read_status_mask = Rx_OVR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (iflag & INPCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) up->port.read_status_mask |= CRC_ERR | PAR_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (iflag & (IGNBRK | BRKINT | PARMRK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) up->port.read_status_mask |= BRK_ABRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) up->port.ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) up->port.ignore_status_mask |= CRC_ERR | PAR_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (iflag & IGNBRK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) up->port.ignore_status_mask |= BRK_ABRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) up->port.ignore_status_mask |= Rx_OVR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if ((cflag & CREAD) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) up->port.ignore_status_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* The port lock is not held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) sunzilog_set_termios(struct uart_port *port, struct ktermios *termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int baud, brg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) spin_lock_irqsave(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sunzilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (UART_ENABLE_MS(&up->port, termios->c_cflag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) up->flags |= SUNZILOG_FLAG_MODEM_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) up->flags &= ~SUNZILOG_FLAG_MODEM_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) up->cflag = termios->c_cflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) uart_update_timeout(port, termios->c_cflag, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) spin_unlock_irqrestore(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) static const char *sunzilog_type(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct uart_sunzilog_port *up = UART_ZILOG(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /* We do not request/release mappings of the registers here, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * happens at early serial probe time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static void sunzilog_release_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int sunzilog_request_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* These do not need to do anything interesting either. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) static void sunzilog_config_port(struct uart_port *port, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /* We do not support letting the user mess with the divisor, IRQ, etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static int sunzilog_verify_port(struct uart_port *port, struct serial_struct *ser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) #ifdef CONFIG_CONSOLE_POLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static int sunzilog_get_poll_char(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) unsigned char ch, r1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct zilog_channel __iomem *channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) r1 = read_zsreg(channel, R1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) writeb(ERR_RES, &channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) ch = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* This funny hack depends upon BRK_ABRT not interfering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * with the other bits we care about in R1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (ch & BRK_ABRT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) r1 |= BRK_ABRT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (!(ch & Rx_CH_AV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return NO_POLL_CHAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) ch = readb(&channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) ch &= up->parity_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) static void sunzilog_put_poll_char(struct uart_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) unsigned char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct uart_sunzilog_port *up =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) container_of(port, struct uart_sunzilog_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) sunzilog_putchar(&up->port, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) #endif /* CONFIG_CONSOLE_POLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static const struct uart_ops sunzilog_pops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) .tx_empty = sunzilog_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) .set_mctrl = sunzilog_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) .get_mctrl = sunzilog_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .stop_tx = sunzilog_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .start_tx = sunzilog_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .stop_rx = sunzilog_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .enable_ms = sunzilog_enable_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) .break_ctl = sunzilog_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) .startup = sunzilog_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) .shutdown = sunzilog_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) .set_termios = sunzilog_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) .type = sunzilog_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) .release_port = sunzilog_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .request_port = sunzilog_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .config_port = sunzilog_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .verify_port = sunzilog_verify_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) #ifdef CONFIG_CONSOLE_POLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .poll_get_char = sunzilog_get_poll_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .poll_put_char = sunzilog_put_poll_char,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) static int uart_chip_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) static struct uart_sunzilog_port *sunzilog_port_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static struct zilog_layout __iomem **sunzilog_chip_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static struct uart_sunzilog_port *sunzilog_irq_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static struct uart_driver sunzilog_reg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) .driver_name = "sunzilog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .dev_name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) .major = TTY_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) static int __init sunzilog_alloc_tables(int num_sunzilog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct uart_sunzilog_port *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int num_channels = num_sunzilog * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) size = num_channels * sizeof(struct uart_sunzilog_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) sunzilog_port_table = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!sunzilog_port_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) for (i = 0; i < num_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) up = &sunzilog_port_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) spin_lock_init(&up->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) sunzilog_irq_chain = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (i < num_channels - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) up->next = up + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) up->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) size = num_sunzilog * sizeof(struct zilog_layout __iomem *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) sunzilog_chip_regs = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (!sunzilog_chip_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) kfree(sunzilog_port_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) sunzilog_irq_chain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static void sunzilog_free_tables(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) kfree(sunzilog_port_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) sunzilog_irq_chain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) kfree(sunzilog_chip_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) static void sunzilog_putchar(struct uart_port *port, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) int loops = ZS_PUT_CHAR_MAX_DELAY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* This is a timed polling loop so do not switch the explicit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) unsigned char val = readb(&channel->control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (val & Tx_BUF_EMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) } while (--loops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) writeb(ch, &channel->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ZSDELAY();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ZS_WSYNC(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static DEFINE_SPINLOCK(sunzilog_serio_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct uart_sunzilog_port *up = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) spin_lock_irqsave(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) sunzilog_putchar(&up->port, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static int sunzilog_serio_open(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct uart_sunzilog_port *up = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) spin_lock_irqsave(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (!up->serio_open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) up->serio_open = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) static void sunzilog_serio_close(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct uart_sunzilog_port *up = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) spin_lock_irqsave(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) up->serio_open = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) #endif /* CONFIG_SERIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) #ifdef CONFIG_SERIAL_SUNZILOG_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) sunzilog_console_write(struct console *con, const char *s, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) int locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (up->port.sysrq || oops_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) locked = spin_trylock_irqsave(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) spin_lock_irqsave(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) uart_console_write(&up->port, s, count, sunzilog_putchar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) spin_unlock_irqrestore(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static int __init sunzilog_console_setup(struct console *con, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int baud, brg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (up->port.type != PORT_SUNZILOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) (sunzilog_reg.minor - 64) + con->index, con->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) /* Get firmware console settings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) sunserial_console_termios(con, up->port.dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) /* Firmware console speed is limited to 150-->38400 baud so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * this hackish cflag thing is OK.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) switch (con->cflag & CBAUD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) case B150: baud = 150; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) case B300: baud = 300; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) case B600: baud = 600; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) case B1200: baud = 1200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) case B2400: baud = 2400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) case B4800: baud = 4800; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) default: case B9600: baud = 9600; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) case B19200: baud = 19200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) case B38400: baud = 38400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) spin_lock_irqsave(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) up->curregs[R15] |= BRKIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) sunzilog_convert_to_zs(up, con->cflag, 0, brg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) __sunzilog_startup(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) spin_unlock_irqrestore(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static struct console sunzilog_console_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) .name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) .write = sunzilog_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) .device = uart_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) .setup = sunzilog_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .data = &sunzilog_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static inline struct console *SUNZILOG_CONSOLE(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return &sunzilog_console_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) #define SUNZILOG_CONSOLE() (NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) static void sunzilog_init_kbdms(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) int baud, brg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) up->cflag = B1200 | CS8 | CLOCAL | CREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) baud = 1200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) up->cflag = B4800 | CS8 | CLOCAL | CREAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) baud = 4800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) up->curregs[R15] |= BRKIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) sunzilog_convert_to_zs(up, up->cflag, 0, brg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) __sunzilog_startup(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) static void sunzilog_register_serio(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) struct serio *serio = &up->serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) serio->port_data = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) serio->id.type = SERIO_RS232;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (up->flags & SUNZILOG_FLAG_CONS_KEYB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) serio->id.proto = SERIO_SUNKBD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) strlcpy(serio->name, "zskbd", sizeof(serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) serio->id.proto = SERIO_SUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) serio->id.extra = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) strlcpy(serio->name, "zsms", sizeof(serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) strlcpy(serio->phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) ((up->flags & SUNZILOG_FLAG_CONS_KEYB) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) "zs/serio0" : "zs/serio1"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) sizeof(serio->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) serio->write = sunzilog_serio_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) serio->open = sunzilog_serio_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) serio->close = sunzilog_serio_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) serio->dev.parent = up->port.dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) serio_register_port(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static void sunzilog_init_hw(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) int baud, brg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) spin_lock_irqsave(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (ZS_IS_CHANNEL_A(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) write_zsreg(channel, R9, FHWRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) ZSDELAY_LONG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) (void) read_zsreg(channel, R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) SUNZILOG_FLAG_CONS_MOUSE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) up->curregs[R3] = RxENAB | Rx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) up->curregs[R5] = TxENAB | Tx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) up->curregs[R6] = 0x00; /* SDLC Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) up->curregs[R7] = 0x7E; /* SDLC Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) up->curregs[R9] = NV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) up->curregs[R7p] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) sunzilog_init_kbdms(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* Only enable interrupts if an ISR handler available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) up->curregs[R9] |= MIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) write_zsreg(channel, R9, up->curregs[R9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) /* Normal serial TTY. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) up->parity_mask = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) up->curregs[R3] = RxENAB | Rx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) up->curregs[R5] = TxENAB | Tx8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) up->curregs[R6] = 0x00; /* SDLC Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) up->curregs[R7] = 0x7E; /* SDLC Flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) up->curregs[R9] = NV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) up->curregs[R10] = NRZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) up->curregs[R11] = TCBR | RCBR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) baud = 9600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) up->curregs[R12] = (brg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) up->curregs[R13] = (brg >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) up->curregs[R14] = BRSRC | BRENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) if (__load_zsregs(channel, up->curregs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) up->flags |= SUNZILOG_FLAG_ESCC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* Only enable interrupts if an ISR handler available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) up->curregs[R9] |= MIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) write_zsreg(channel, R9, up->curregs[R9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) spin_unlock_irqrestore(&up->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) SUNZILOG_FLAG_CONS_MOUSE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) sunzilog_register_serio(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static int zilog_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) static int zs_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static int kbm_inst, uart_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) int inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct uart_sunzilog_port *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct zilog_layout __iomem *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) int keyboard_mouse = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (of_find_property(op->dev.of_node, "keyboard", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) keyboard_mouse = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /* uarts must come before keyboards/mice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (keyboard_mouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) inst = uart_chip_count + kbm_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) inst = uart_inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) sizeof(struct zilog_layout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) "zs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (!sunzilog_chip_regs[inst])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) rp = sunzilog_chip_regs[inst];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (!zilog_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) zilog_irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) up = &sunzilog_port_table[inst * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* Channel A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) up[0].port.mapbase = op->resource[0].start + 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) up[0].port.membase = (void __iomem *) &rp->channelA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) up[0].port.iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) up[0].port.irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) up[0].port.uartclk = ZS_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) up[0].port.fifosize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) up[0].port.ops = &sunzilog_pops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) up[0].port.type = PORT_SUNZILOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) up[0].port.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) up[0].port.line = (inst * 2) + 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) up[0].port.dev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) up[0].flags |= SUNZILOG_FLAG_IS_CHANNEL_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) up[0].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNZILOG_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (keyboard_mouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) up[0].flags |= SUNZILOG_FLAG_CONS_KEYB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) sunzilog_init_hw(&up[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* Channel B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) up[1].port.mapbase = op->resource[0].start + 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) up[1].port.membase = (void __iomem *) &rp->channelB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) up[1].port.iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) up[1].port.irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) up[1].port.uartclk = ZS_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) up[1].port.fifosize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) up[1].port.ops = &sunzilog_pops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) up[1].port.type = PORT_SUNZILOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) up[1].port.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) up[1].port.line = (inst * 2) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) up[1].port.dev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) up[1].flags |= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) up[1].port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_SUNZILOG_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (keyboard_mouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) up[1].flags |= SUNZILOG_FLAG_CONS_MOUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) sunzilog_init_hw(&up[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (!keyboard_mouse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) &sunzilog_reg, up[0].port.line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) up->flags |= SUNZILOG_FLAG_IS_CONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) err = uart_add_one_port(&sunzilog_reg, &up[0].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) of_iounmap(&op->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) rp, sizeof(struct zilog_layout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (sunserial_console_match(SUNZILOG_CONSOLE(), op->dev.of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) &sunzilog_reg, up[1].port.line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) up->flags |= SUNZILOG_FLAG_IS_CONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) err = uart_add_one_port(&sunzilog_reg, &up[1].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) uart_remove_one_port(&sunzilog_reg, &up[0].port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) of_iounmap(&op->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) rp, sizeof(struct zilog_layout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) uart_inst++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) "is a %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) dev_name(&op->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) (unsigned long long) up[0].port.mapbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) op->archdata.irqs[0], sunzilog_type(&up[0].port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) "is a %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) dev_name(&op->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) (unsigned long long) up[1].port.mapbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) op->archdata.irqs[0], sunzilog_type(&up[1].port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) kbm_inst++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) platform_set_drvdata(op, &up[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) static void zs_remove_one(struct uart_sunzilog_port *up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) #ifdef CONFIG_SERIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) serio_unregister_port(&up->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) uart_remove_one_port(&sunzilog_reg, &up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) static int zs_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct uart_sunzilog_port *up = platform_get_drvdata(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) struct zilog_layout __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) zs_remove_one(&up[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) zs_remove_one(&up[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) regs = sunzilog_chip_regs[up[0].port.line / 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) of_iounmap(&op->resource[0], regs, sizeof(struct zilog_layout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) static const struct of_device_id zs_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) .name = "zs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) MODULE_DEVICE_TABLE(of, zs_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) static struct platform_driver zs_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) .name = "zs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) .of_match_table = zs_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) .probe = zs_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) .remove = zs_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) static int __init sunzilog_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) struct device_node *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) int num_keybms = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) int num_sunzilog = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) for_each_node_by_name(dp, "zs") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) num_sunzilog++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (of_find_property(dp, "keyboard", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) num_keybms++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (num_sunzilog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) err = sunzilog_alloc_tables(num_sunzilog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) uart_chip_count = num_sunzilog - num_keybms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) err = sunserial_register_minors(&sunzilog_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) uart_chip_count * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) goto out_free_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) err = platform_driver_register(&zs_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) goto out_unregister_uart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) if (zilog_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) struct uart_sunzilog_port *up = sunzilog_irq_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) "zs", sunzilog_irq_chain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) goto out_unregister_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) /* Enable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) while (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) up->flags |= SUNZILOG_FLAG_ISR_HANDLER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) up->curregs[R9] |= MIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) write_zsreg(channel, R9, up->curregs[R9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) up = up->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) out_unregister_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) platform_driver_unregister(&zs_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) out_unregister_uart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (num_sunzilog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) sunserial_unregister_minors(&sunzilog_reg, num_sunzilog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) sunzilog_reg.cons = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) out_free_tables:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) sunzilog_free_tables();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) static void __exit sunzilog_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) platform_driver_unregister(&zs_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (zilog_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) struct uart_sunzilog_port *up = sunzilog_irq_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) /* Disable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) while (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) struct zilog_channel __iomem *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) up->curregs[R9] &= ~MIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) write_zsreg(channel, R9, up->curregs[R9]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) up = up->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) free_irq(zilog_irq, sunzilog_irq_chain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) zilog_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) if (sunzilog_reg.nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) sunserial_unregister_minors(&sunzilog_reg, sunzilog_reg.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) sunzilog_free_tables();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) module_init(sunzilog_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) module_exit(sunzilog_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) MODULE_AUTHOR("David S. Miller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) MODULE_DESCRIPTION("Sun Zilog serial port driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) MODULE_VERSION("2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) MODULE_LICENSE("GPL");