Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");