18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Base port operations for 8250/16550-type serial ports
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
68c2ecf20Sopenharmony_ci *  Split from 8250_core.c, Copyright (C) 2001 Russell King.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * A note about mapbase / membase
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *  mapbase is the physical address of the IO port.
118c2ecf20Sopenharmony_ci *  membase is an 'ioremapped' cookie.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
168c2ecf20Sopenharmony_ci#include <linux/ioport.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/irq.h>
198c2ecf20Sopenharmony_ci#include <linux/console.h>
208c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
218c2ecf20Sopenharmony_ci#include <linux/sysrq.h>
228c2ecf20Sopenharmony_ci#include <linux/delay.h>
238c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
248c2ecf20Sopenharmony_ci#include <linux/tty.h>
258c2ecf20Sopenharmony_ci#include <linux/ratelimit.h>
268c2ecf20Sopenharmony_ci#include <linux/tty_flip.h>
278c2ecf20Sopenharmony_ci#include <linux/serial.h>
288c2ecf20Sopenharmony_ci#include <linux/serial_8250.h>
298c2ecf20Sopenharmony_ci#include <linux/nmi.h>
308c2ecf20Sopenharmony_ci#include <linux/mutex.h>
318c2ecf20Sopenharmony_ci#include <linux/slab.h>
328c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
338c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
348c2ecf20Sopenharmony_ci#include <linux/ktime.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <asm/io.h>
378c2ecf20Sopenharmony_ci#include <asm/irq.h>
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include "8250.h"
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* Nuvoton NPCM timeout register */
428c2ecf20Sopenharmony_ci#define UART_NPCM_TOR          7
438c2ecf20Sopenharmony_ci#define UART_NPCM_TOIE         BIT(7)  /* Timeout Interrupt Enable */
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * Debugging.
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci#if 0
498c2ecf20Sopenharmony_ci#define DEBUG_AUTOCONF(fmt...)	printk(fmt)
508c2ecf20Sopenharmony_ci#else
518c2ecf20Sopenharmony_ci#define DEBUG_AUTOCONF(fmt...)	do { } while (0)
528c2ecf20Sopenharmony_ci#endif
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define BOTH_EMPTY	(UART_LSR_TEMT | UART_LSR_THRE)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/*
578c2ecf20Sopenharmony_ci * Here we define the default xmit fifo size used for each type of UART.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_cistatic const struct serial8250_config uart_config[] = {
608c2ecf20Sopenharmony_ci	[PORT_UNKNOWN] = {
618c2ecf20Sopenharmony_ci		.name		= "unknown",
628c2ecf20Sopenharmony_ci		.fifo_size	= 1,
638c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
648c2ecf20Sopenharmony_ci	},
658c2ecf20Sopenharmony_ci	[PORT_8250] = {
668c2ecf20Sopenharmony_ci		.name		= "8250",
678c2ecf20Sopenharmony_ci		.fifo_size	= 1,
688c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
698c2ecf20Sopenharmony_ci	},
708c2ecf20Sopenharmony_ci	[PORT_16450] = {
718c2ecf20Sopenharmony_ci		.name		= "16450",
728c2ecf20Sopenharmony_ci		.fifo_size	= 1,
738c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
748c2ecf20Sopenharmony_ci	},
758c2ecf20Sopenharmony_ci	[PORT_16550] = {
768c2ecf20Sopenharmony_ci		.name		= "16550",
778c2ecf20Sopenharmony_ci		.fifo_size	= 1,
788c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
798c2ecf20Sopenharmony_ci	},
808c2ecf20Sopenharmony_ci	[PORT_16550A] = {
818c2ecf20Sopenharmony_ci		.name		= "16550A",
828c2ecf20Sopenharmony_ci		.fifo_size	= 16,
838c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
848c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
858c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 4, 8, 14},
868c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
878c2ecf20Sopenharmony_ci	},
888c2ecf20Sopenharmony_ci	[PORT_CIRRUS] = {
898c2ecf20Sopenharmony_ci		.name		= "Cirrus",
908c2ecf20Sopenharmony_ci		.fifo_size	= 1,
918c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
928c2ecf20Sopenharmony_ci	},
938c2ecf20Sopenharmony_ci	[PORT_16650] = {
948c2ecf20Sopenharmony_ci		.name		= "ST16650",
958c2ecf20Sopenharmony_ci		.fifo_size	= 1,
968c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
978c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
988c2ecf20Sopenharmony_ci	},
998c2ecf20Sopenharmony_ci	[PORT_16650V2] = {
1008c2ecf20Sopenharmony_ci		.name		= "ST16650V2",
1018c2ecf20Sopenharmony_ci		.fifo_size	= 32,
1028c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
1038c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
1048c2ecf20Sopenharmony_ci				  UART_FCR_T_TRIG_00,
1058c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {8, 16, 24, 28},
1068c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
1078c2ecf20Sopenharmony_ci	},
1088c2ecf20Sopenharmony_ci	[PORT_16750] = {
1098c2ecf20Sopenharmony_ci		.name		= "TI16750",
1108c2ecf20Sopenharmony_ci		.fifo_size	= 64,
1118c2ecf20Sopenharmony_ci		.tx_loadsz	= 64,
1128c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
1138c2ecf20Sopenharmony_ci				  UART_FCR7_64BYTE,
1148c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 16, 32, 56},
1158c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
1168c2ecf20Sopenharmony_ci	},
1178c2ecf20Sopenharmony_ci	[PORT_STARTECH] = {
1188c2ecf20Sopenharmony_ci		.name		= "Startech",
1198c2ecf20Sopenharmony_ci		.fifo_size	= 1,
1208c2ecf20Sopenharmony_ci		.tx_loadsz	= 1,
1218c2ecf20Sopenharmony_ci	},
1228c2ecf20Sopenharmony_ci	[PORT_16C950] = {
1238c2ecf20Sopenharmony_ci		.name		= "16C950/954",
1248c2ecf20Sopenharmony_ci		.fifo_size	= 128,
1258c2ecf20Sopenharmony_ci		.tx_loadsz	= 128,
1268c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
1278c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {16, 32, 112, 120},
1288c2ecf20Sopenharmony_ci		/* UART_CAP_EFR breaks billionon CF bluetooth card. */
1298c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP,
1308c2ecf20Sopenharmony_ci	},
1318c2ecf20Sopenharmony_ci	[PORT_16654] = {
1328c2ecf20Sopenharmony_ci		.name		= "ST16654",
1338c2ecf20Sopenharmony_ci		.fifo_size	= 64,
1348c2ecf20Sopenharmony_ci		.tx_loadsz	= 32,
1358c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
1368c2ecf20Sopenharmony_ci				  UART_FCR_T_TRIG_10,
1378c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {8, 16, 56, 60},
1388c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
1398c2ecf20Sopenharmony_ci	},
1408c2ecf20Sopenharmony_ci	[PORT_16850] = {
1418c2ecf20Sopenharmony_ci		.name		= "XR16850",
1428c2ecf20Sopenharmony_ci		.fifo_size	= 128,
1438c2ecf20Sopenharmony_ci		.tx_loadsz	= 128,
1448c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
1458c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
1468c2ecf20Sopenharmony_ci	},
1478c2ecf20Sopenharmony_ci	[PORT_RSA] = {
1488c2ecf20Sopenharmony_ci		.name		= "RSA",
1498c2ecf20Sopenharmony_ci		.fifo_size	= 2048,
1508c2ecf20Sopenharmony_ci		.tx_loadsz	= 2048,
1518c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
1528c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
1538c2ecf20Sopenharmony_ci	},
1548c2ecf20Sopenharmony_ci	[PORT_NS16550A] = {
1558c2ecf20Sopenharmony_ci		.name		= "NS16550A",
1568c2ecf20Sopenharmony_ci		.fifo_size	= 16,
1578c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
1588c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
1598c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_NATSEMI,
1608c2ecf20Sopenharmony_ci	},
1618c2ecf20Sopenharmony_ci	[PORT_XSCALE] = {
1628c2ecf20Sopenharmony_ci		.name		= "XScale",
1638c2ecf20Sopenharmony_ci		.fifo_size	= 32,
1648c2ecf20Sopenharmony_ci		.tx_loadsz	= 32,
1658c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
1668c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
1678c2ecf20Sopenharmony_ci	},
1688c2ecf20Sopenharmony_ci	[PORT_OCTEON] = {
1698c2ecf20Sopenharmony_ci		.name		= "OCTEON",
1708c2ecf20Sopenharmony_ci		.fifo_size	= 64,
1718c2ecf20Sopenharmony_ci		.tx_loadsz	= 64,
1728c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
1738c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
1748c2ecf20Sopenharmony_ci	},
1758c2ecf20Sopenharmony_ci	[PORT_AR7] = {
1768c2ecf20Sopenharmony_ci		.name		= "AR7",
1778c2ecf20Sopenharmony_ci		.fifo_size	= 16,
1788c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
1798c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
1808c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO /* | UART_CAP_AFE */,
1818c2ecf20Sopenharmony_ci	},
1828c2ecf20Sopenharmony_ci	[PORT_U6_16550A] = {
1838c2ecf20Sopenharmony_ci		.name		= "U6_16550A",
1848c2ecf20Sopenharmony_ci		.fifo_size	= 64,
1858c2ecf20Sopenharmony_ci		.tx_loadsz	= 64,
1868c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
1878c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
1888c2ecf20Sopenharmony_ci	},
1898c2ecf20Sopenharmony_ci	[PORT_TEGRA] = {
1908c2ecf20Sopenharmony_ci		.name		= "Tegra",
1918c2ecf20Sopenharmony_ci		.fifo_size	= 32,
1928c2ecf20Sopenharmony_ci		.tx_loadsz	= 8,
1938c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
1948c2ecf20Sopenharmony_ci				  UART_FCR_T_TRIG_01,
1958c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 4, 8, 14},
1968c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_RTOIE,
1978c2ecf20Sopenharmony_ci	},
1988c2ecf20Sopenharmony_ci	[PORT_XR17D15X] = {
1998c2ecf20Sopenharmony_ci		.name		= "XR17D15X",
2008c2ecf20Sopenharmony_ci		.fifo_size	= 64,
2018c2ecf20Sopenharmony_ci		.tx_loadsz	= 64,
2028c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
2038c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
2048c2ecf20Sopenharmony_ci				  UART_CAP_SLEEP,
2058c2ecf20Sopenharmony_ci	},
2068c2ecf20Sopenharmony_ci	[PORT_XR17V35X] = {
2078c2ecf20Sopenharmony_ci		.name		= "XR17V35X",
2088c2ecf20Sopenharmony_ci		.fifo_size	= 256,
2098c2ecf20Sopenharmony_ci		.tx_loadsz	= 256,
2108c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
2118c2ecf20Sopenharmony_ci				  UART_FCR_T_TRIG_11,
2128c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
2138c2ecf20Sopenharmony_ci				  UART_CAP_SLEEP,
2148c2ecf20Sopenharmony_ci	},
2158c2ecf20Sopenharmony_ci	[PORT_LPC3220] = {
2168c2ecf20Sopenharmony_ci		.name		= "LPC3220",
2178c2ecf20Sopenharmony_ci		.fifo_size	= 64,
2188c2ecf20Sopenharmony_ci		.tx_loadsz	= 32,
2198c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
2208c2ecf20Sopenharmony_ci				  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
2218c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
2228c2ecf20Sopenharmony_ci	},
2238c2ecf20Sopenharmony_ci	[PORT_BRCM_TRUMANAGE] = {
2248c2ecf20Sopenharmony_ci		.name		= "TruManage",
2258c2ecf20Sopenharmony_ci		.fifo_size	= 1,
2268c2ecf20Sopenharmony_ci		.tx_loadsz	= 1024,
2278c2ecf20Sopenharmony_ci		.flags		= UART_CAP_HFIFO,
2288c2ecf20Sopenharmony_ci	},
2298c2ecf20Sopenharmony_ci	[PORT_8250_CIR] = {
2308c2ecf20Sopenharmony_ci		.name		= "CIR port"
2318c2ecf20Sopenharmony_ci	},
2328c2ecf20Sopenharmony_ci	[PORT_ALTR_16550_F32] = {
2338c2ecf20Sopenharmony_ci		.name		= "Altera 16550 FIFO32",
2348c2ecf20Sopenharmony_ci		.fifo_size	= 32,
2358c2ecf20Sopenharmony_ci		.tx_loadsz	= 32,
2368c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
2378c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 8, 16, 30},
2388c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
2398c2ecf20Sopenharmony_ci	},
2408c2ecf20Sopenharmony_ci	[PORT_ALTR_16550_F64] = {
2418c2ecf20Sopenharmony_ci		.name		= "Altera 16550 FIFO64",
2428c2ecf20Sopenharmony_ci		.fifo_size	= 64,
2438c2ecf20Sopenharmony_ci		.tx_loadsz	= 64,
2448c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
2458c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 16, 32, 62},
2468c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
2478c2ecf20Sopenharmony_ci	},
2488c2ecf20Sopenharmony_ci	[PORT_ALTR_16550_F128] = {
2498c2ecf20Sopenharmony_ci		.name		= "Altera 16550 FIFO128",
2508c2ecf20Sopenharmony_ci		.fifo_size	= 128,
2518c2ecf20Sopenharmony_ci		.tx_loadsz	= 128,
2528c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
2538c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 32, 64, 126},
2548c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
2558c2ecf20Sopenharmony_ci	},
2568c2ecf20Sopenharmony_ci	/*
2578c2ecf20Sopenharmony_ci	 * tx_loadsz is set to 63-bytes instead of 64-bytes to implement
2588c2ecf20Sopenharmony_ci	 * workaround of errata A-008006 which states that tx_loadsz should
2598c2ecf20Sopenharmony_ci	 * be configured less than Maximum supported fifo bytes.
2608c2ecf20Sopenharmony_ci	 */
2618c2ecf20Sopenharmony_ci	[PORT_16550A_FSL64] = {
2628c2ecf20Sopenharmony_ci		.name		= "16550A_FSL64",
2638c2ecf20Sopenharmony_ci		.fifo_size	= 64,
2648c2ecf20Sopenharmony_ci		.tx_loadsz	= 63,
2658c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
2668c2ecf20Sopenharmony_ci				  UART_FCR7_64BYTE,
2678c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
2688c2ecf20Sopenharmony_ci	},
2698c2ecf20Sopenharmony_ci	[PORT_RT2880] = {
2708c2ecf20Sopenharmony_ci		.name		= "Palmchip BK-3103",
2718c2ecf20Sopenharmony_ci		.fifo_size	= 16,
2728c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
2738c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
2748c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 4, 8, 14},
2758c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
2768c2ecf20Sopenharmony_ci	},
2778c2ecf20Sopenharmony_ci	[PORT_DA830] = {
2788c2ecf20Sopenharmony_ci		.name		= "TI DA8xx/66AK2x",
2798c2ecf20Sopenharmony_ci		.fifo_size	= 16,
2808c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
2818c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
2828c2ecf20Sopenharmony_ci				  UART_FCR_R_TRIG_10,
2838c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 4, 8, 14},
2848c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_AFE,
2858c2ecf20Sopenharmony_ci	},
2868c2ecf20Sopenharmony_ci	[PORT_MTK_BTIF] = {
2878c2ecf20Sopenharmony_ci		.name		= "MediaTek BTIF",
2888c2ecf20Sopenharmony_ci		.fifo_size	= 16,
2898c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
2908c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO |
2918c2ecf20Sopenharmony_ci				  UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
2928c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
2938c2ecf20Sopenharmony_ci	},
2948c2ecf20Sopenharmony_ci	[PORT_NPCM] = {
2958c2ecf20Sopenharmony_ci		.name		= "Nuvoton 16550",
2968c2ecf20Sopenharmony_ci		.fifo_size	= 16,
2978c2ecf20Sopenharmony_ci		.tx_loadsz	= 16,
2988c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
2998c2ecf20Sopenharmony_ci				  UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
3008c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 4, 8, 14},
3018c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO,
3028c2ecf20Sopenharmony_ci	},
3038c2ecf20Sopenharmony_ci	[PORT_SUNIX] = {
3048c2ecf20Sopenharmony_ci		.name		= "Sunix",
3058c2ecf20Sopenharmony_ci		.fifo_size	= 128,
3068c2ecf20Sopenharmony_ci		.tx_loadsz	= 128,
3078c2ecf20Sopenharmony_ci		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
3088c2ecf20Sopenharmony_ci		.rxtrig_bytes	= {1, 32, 64, 112},
3098c2ecf20Sopenharmony_ci		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP,
3108c2ecf20Sopenharmony_ci	},
3118c2ecf20Sopenharmony_ci};
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci/* Uart divisor latch read */
3148c2ecf20Sopenharmony_cistatic int default_serial_dl_read(struct uart_8250_port *up)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	/* Assign these in pieces to truncate any bits above 7.  */
3178c2ecf20Sopenharmony_ci	unsigned char dll = serial_in(up, UART_DLL);
3188c2ecf20Sopenharmony_ci	unsigned char dlm = serial_in(up, UART_DLM);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	return dll | dlm << 8;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/* Uart divisor latch write */
3248c2ecf20Sopenharmony_cistatic void default_serial_dl_write(struct uart_8250_port *up, int value)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	serial_out(up, UART_DLL, value & 0xff);
3278c2ecf20Sopenharmony_ci	serial_out(up, UART_DLM, value >> 8 & 0xff);
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RT288X
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* Au1x00/RT288x UART hardware has a weird register layout */
3338c2ecf20Sopenharmony_cistatic const s8 au_io_in_map[8] = {
3348c2ecf20Sopenharmony_ci	 0,	/* UART_RX  */
3358c2ecf20Sopenharmony_ci	 2,	/* UART_IER */
3368c2ecf20Sopenharmony_ci	 3,	/* UART_IIR */
3378c2ecf20Sopenharmony_ci	 5,	/* UART_LCR */
3388c2ecf20Sopenharmony_ci	 6,	/* UART_MCR */
3398c2ecf20Sopenharmony_ci	 7,	/* UART_LSR */
3408c2ecf20Sopenharmony_ci	 8,	/* UART_MSR */
3418c2ecf20Sopenharmony_ci	-1,	/* UART_SCR (unmapped) */
3428c2ecf20Sopenharmony_ci};
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic const s8 au_io_out_map[8] = {
3458c2ecf20Sopenharmony_ci	 1,	/* UART_TX  */
3468c2ecf20Sopenharmony_ci	 2,	/* UART_IER */
3478c2ecf20Sopenharmony_ci	 4,	/* UART_FCR */
3488c2ecf20Sopenharmony_ci	 5,	/* UART_LCR */
3498c2ecf20Sopenharmony_ci	 6,	/* UART_MCR */
3508c2ecf20Sopenharmony_ci	-1,	/* UART_LSR (unmapped) */
3518c2ecf20Sopenharmony_ci	-1,	/* UART_MSR (unmapped) */
3528c2ecf20Sopenharmony_ci	-1,	/* UART_SCR (unmapped) */
3538c2ecf20Sopenharmony_ci};
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ciunsigned int au_serial_in(struct uart_port *p, int offset)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	if (offset >= ARRAY_SIZE(au_io_in_map))
3588c2ecf20Sopenharmony_ci		return UINT_MAX;
3598c2ecf20Sopenharmony_ci	offset = au_io_in_map[offset];
3608c2ecf20Sopenharmony_ci	if (offset < 0)
3618c2ecf20Sopenharmony_ci		return UINT_MAX;
3628c2ecf20Sopenharmony_ci	return __raw_readl(p->membase + (offset << p->regshift));
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_civoid au_serial_out(struct uart_port *p, int offset, int value)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	if (offset >= ARRAY_SIZE(au_io_out_map))
3688c2ecf20Sopenharmony_ci		return;
3698c2ecf20Sopenharmony_ci	offset = au_io_out_map[offset];
3708c2ecf20Sopenharmony_ci	if (offset < 0)
3718c2ecf20Sopenharmony_ci		return;
3728c2ecf20Sopenharmony_ci	__raw_writel(value, p->membase + (offset << p->regshift));
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/* Au1x00 haven't got a standard divisor latch */
3768c2ecf20Sopenharmony_cistatic int au_serial_dl_read(struct uart_8250_port *up)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	return __raw_readl(up->port.membase + 0x28);
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic void au_serial_dl_write(struct uart_8250_port *up, int value)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	__raw_writel(value, up->port.membase + 0x28);
3848c2ecf20Sopenharmony_ci}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci#endif
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic unsigned int hub6_serial_in(struct uart_port *p, int offset)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
3918c2ecf20Sopenharmony_ci	outb(p->hub6 - 1 + offset, p->iobase);
3928c2ecf20Sopenharmony_ci	return inb(p->iobase + 1);
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic void hub6_serial_out(struct uart_port *p, int offset, int value)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
3988c2ecf20Sopenharmony_ci	outb(p->hub6 - 1 + offset, p->iobase);
3998c2ecf20Sopenharmony_ci	outb(value, p->iobase + 1);
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic unsigned int mem_serial_in(struct uart_port *p, int offset)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4058c2ecf20Sopenharmony_ci	return readb(p->membase + offset);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic void mem_serial_out(struct uart_port *p, int offset, int value)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4118c2ecf20Sopenharmony_ci	writeb(value, p->membase + offset);
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic void mem16_serial_out(struct uart_port *p, int offset, int value)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4178c2ecf20Sopenharmony_ci	writew(value, p->membase + offset);
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic unsigned int mem16_serial_in(struct uart_port *p, int offset)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4238c2ecf20Sopenharmony_ci	return readw(p->membase + offset);
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic void mem32_serial_out(struct uart_port *p, int offset, int value)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4298c2ecf20Sopenharmony_ci	writel(value, p->membase + offset);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic unsigned int mem32_serial_in(struct uart_port *p, int offset)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4358c2ecf20Sopenharmony_ci	return readl(p->membase + offset);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_cistatic void mem32be_serial_out(struct uart_port *p, int offset, int value)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4418c2ecf20Sopenharmony_ci	iowrite32be(value, p->membase + offset);
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic unsigned int mem32be_serial_in(struct uart_port *p, int offset)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4478c2ecf20Sopenharmony_ci	return ioread32be(p->membase + offset);
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic unsigned int io_serial_in(struct uart_port *p, int offset)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4538c2ecf20Sopenharmony_ci	return inb(p->iobase + offset);
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic void io_serial_out(struct uart_port *p, int offset, int value)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	offset = offset << p->regshift;
4598c2ecf20Sopenharmony_ci	outb(value, p->iobase + offset);
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic int serial8250_default_handle_irq(struct uart_port *port);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic void set_io_from_upio(struct uart_port *p)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(p);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	up->dl_read = default_serial_dl_read;
4698c2ecf20Sopenharmony_ci	up->dl_write = default_serial_dl_write;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	switch (p->iotype) {
4728c2ecf20Sopenharmony_ci	case UPIO_HUB6:
4738c2ecf20Sopenharmony_ci		p->serial_in = hub6_serial_in;
4748c2ecf20Sopenharmony_ci		p->serial_out = hub6_serial_out;
4758c2ecf20Sopenharmony_ci		break;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	case UPIO_MEM:
4788c2ecf20Sopenharmony_ci		p->serial_in = mem_serial_in;
4798c2ecf20Sopenharmony_ci		p->serial_out = mem_serial_out;
4808c2ecf20Sopenharmony_ci		break;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	case UPIO_MEM16:
4838c2ecf20Sopenharmony_ci		p->serial_in = mem16_serial_in;
4848c2ecf20Sopenharmony_ci		p->serial_out = mem16_serial_out;
4858c2ecf20Sopenharmony_ci		break;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	case UPIO_MEM32:
4888c2ecf20Sopenharmony_ci		p->serial_in = mem32_serial_in;
4898c2ecf20Sopenharmony_ci		p->serial_out = mem32_serial_out;
4908c2ecf20Sopenharmony_ci		break;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	case UPIO_MEM32BE:
4938c2ecf20Sopenharmony_ci		p->serial_in = mem32be_serial_in;
4948c2ecf20Sopenharmony_ci		p->serial_out = mem32be_serial_out;
4958c2ecf20Sopenharmony_ci		break;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RT288X
4988c2ecf20Sopenharmony_ci	case UPIO_AU:
4998c2ecf20Sopenharmony_ci		p->serial_in = au_serial_in;
5008c2ecf20Sopenharmony_ci		p->serial_out = au_serial_out;
5018c2ecf20Sopenharmony_ci		up->dl_read = au_serial_dl_read;
5028c2ecf20Sopenharmony_ci		up->dl_write = au_serial_dl_write;
5038c2ecf20Sopenharmony_ci		break;
5048c2ecf20Sopenharmony_ci#endif
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	default:
5078c2ecf20Sopenharmony_ci		p->serial_in = io_serial_in;
5088c2ecf20Sopenharmony_ci		p->serial_out = io_serial_out;
5098c2ecf20Sopenharmony_ci		break;
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci	/* Remember loaded iotype */
5128c2ecf20Sopenharmony_ci	up->cur_iotype = p->iotype;
5138c2ecf20Sopenharmony_ci	p->handle_irq = serial8250_default_handle_irq;
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic void
5178c2ecf20Sopenharmony_ciserial_port_out_sync(struct uart_port *p, int offset, int value)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	switch (p->iotype) {
5208c2ecf20Sopenharmony_ci	case UPIO_MEM:
5218c2ecf20Sopenharmony_ci	case UPIO_MEM16:
5228c2ecf20Sopenharmony_ci	case UPIO_MEM32:
5238c2ecf20Sopenharmony_ci	case UPIO_MEM32BE:
5248c2ecf20Sopenharmony_ci	case UPIO_AU:
5258c2ecf20Sopenharmony_ci		p->serial_out(p, offset, value);
5268c2ecf20Sopenharmony_ci		p->serial_in(p, UART_LCR);	/* safe, no side-effects */
5278c2ecf20Sopenharmony_ci		break;
5288c2ecf20Sopenharmony_ci	default:
5298c2ecf20Sopenharmony_ci		p->serial_out(p, offset, value);
5308c2ecf20Sopenharmony_ci	}
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci/*
5348c2ecf20Sopenharmony_ci * FIFO support.
5358c2ecf20Sopenharmony_ci */
5368c2ecf20Sopenharmony_cistatic void serial8250_clear_fifos(struct uart_8250_port *p)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	if (p->capabilities & UART_CAP_FIFO) {
5398c2ecf20Sopenharmony_ci		serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
5408c2ecf20Sopenharmony_ci		serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
5418c2ecf20Sopenharmony_ci			       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
5428c2ecf20Sopenharmony_ci		serial_out(p, UART_FCR, 0);
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci}
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_cistatic enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
5478c2ecf20Sopenharmony_cistatic enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_civoid serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	serial8250_clear_fifos(p);
5528c2ecf20Sopenharmony_ci	serial_out(p, UART_FCR, p->fcr);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_civoid serial8250_rpm_get(struct uart_8250_port *p)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	if (!(p->capabilities & UART_CAP_RPM))
5598c2ecf20Sopenharmony_ci		return;
5608c2ecf20Sopenharmony_ci	pm_runtime_get_sync(p->port.dev);
5618c2ecf20Sopenharmony_ci}
5628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_rpm_get);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_civoid serial8250_rpm_put(struct uart_8250_port *p)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	if (!(p->capabilities & UART_CAP_RPM))
5678c2ecf20Sopenharmony_ci		return;
5688c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(p->port.dev);
5698c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(p->port.dev);
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_rpm_put);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci/**
5748c2ecf20Sopenharmony_ci *	serial8250_em485_init() - put uart_8250_port into rs485 emulating
5758c2ecf20Sopenharmony_ci *	@p:	uart_8250_port port instance
5768c2ecf20Sopenharmony_ci *
5778c2ecf20Sopenharmony_ci *	The function is used to start rs485 software emulating on the
5788c2ecf20Sopenharmony_ci *	&struct uart_8250_port* @p. Namely, RTS is switched before/after
5798c2ecf20Sopenharmony_ci *	transmission. The function is idempotent, so it is safe to call it
5808c2ecf20Sopenharmony_ci *	multiple times.
5818c2ecf20Sopenharmony_ci *
5828c2ecf20Sopenharmony_ci *	The caller MUST enable interrupt on empty shift register before
5838c2ecf20Sopenharmony_ci *	calling serial8250_em485_init(). This interrupt is not a part of
5848c2ecf20Sopenharmony_ci *	8250 standard, but implementation defined.
5858c2ecf20Sopenharmony_ci *
5868c2ecf20Sopenharmony_ci *	The function is supposed to be called from .rs485_config callback
5878c2ecf20Sopenharmony_ci *	or from any other callback protected with p->port.lock spinlock.
5888c2ecf20Sopenharmony_ci *
5898c2ecf20Sopenharmony_ci *	See also serial8250_em485_destroy()
5908c2ecf20Sopenharmony_ci *
5918c2ecf20Sopenharmony_ci *	Return 0 - success, -errno - otherwise
5928c2ecf20Sopenharmony_ci */
5938c2ecf20Sopenharmony_cistatic int serial8250_em485_init(struct uart_8250_port *p)
5948c2ecf20Sopenharmony_ci{
5958c2ecf20Sopenharmony_ci	if (p->em485)
5968c2ecf20Sopenharmony_ci		goto deassert_rts;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC);
5998c2ecf20Sopenharmony_ci	if (!p->em485)
6008c2ecf20Sopenharmony_ci		return -ENOMEM;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC,
6038c2ecf20Sopenharmony_ci		     HRTIMER_MODE_REL);
6048c2ecf20Sopenharmony_ci	hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
6058c2ecf20Sopenharmony_ci		     HRTIMER_MODE_REL);
6068c2ecf20Sopenharmony_ci	p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx;
6078c2ecf20Sopenharmony_ci	p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
6088c2ecf20Sopenharmony_ci	p->em485->port = p;
6098c2ecf20Sopenharmony_ci	p->em485->active_timer = NULL;
6108c2ecf20Sopenharmony_ci	p->em485->tx_stopped = true;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cideassert_rts:
6138c2ecf20Sopenharmony_ci	if (p->em485->tx_stopped)
6148c2ecf20Sopenharmony_ci		p->rs485_stop_tx(p);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return 0;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci/**
6208c2ecf20Sopenharmony_ci *	serial8250_em485_destroy() - put uart_8250_port into normal state
6218c2ecf20Sopenharmony_ci *	@p:	uart_8250_port port instance
6228c2ecf20Sopenharmony_ci *
6238c2ecf20Sopenharmony_ci *	The function is used to stop rs485 software emulating on the
6248c2ecf20Sopenharmony_ci *	&struct uart_8250_port* @p. The function is idempotent, so it is safe to
6258c2ecf20Sopenharmony_ci *	call it multiple times.
6268c2ecf20Sopenharmony_ci *
6278c2ecf20Sopenharmony_ci *	The function is supposed to be called from .rs485_config callback
6288c2ecf20Sopenharmony_ci *	or from any other callback protected with p->port.lock spinlock.
6298c2ecf20Sopenharmony_ci *
6308c2ecf20Sopenharmony_ci *	See also serial8250_em485_init()
6318c2ecf20Sopenharmony_ci */
6328c2ecf20Sopenharmony_civoid serial8250_em485_destroy(struct uart_8250_port *p)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	if (!p->em485)
6358c2ecf20Sopenharmony_ci		return;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	hrtimer_cancel(&p->em485->start_tx_timer);
6388c2ecf20Sopenharmony_ci	hrtimer_cancel(&p->em485->stop_tx_timer);
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	kfree(p->em485);
6418c2ecf20Sopenharmony_ci	p->em485 = NULL;
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_em485_destroy);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci/**
6468c2ecf20Sopenharmony_ci * serial8250_em485_config() - generic ->rs485_config() callback
6478c2ecf20Sopenharmony_ci * @port: uart port
6488c2ecf20Sopenharmony_ci * @rs485: rs485 settings
6498c2ecf20Sopenharmony_ci *
6508c2ecf20Sopenharmony_ci * Generic callback usable by 8250 uart drivers to activate rs485 settings
6518c2ecf20Sopenharmony_ci * if the uart is incapable of driving RTS as a Transmit Enable signal in
6528c2ecf20Sopenharmony_ci * hardware, relying on software emulation instead.
6538c2ecf20Sopenharmony_ci */
6548c2ecf20Sopenharmony_ciint serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	/* pick sane settings if the user hasn't */
6598c2ecf20Sopenharmony_ci	if (!!(rs485->flags & SER_RS485_RTS_ON_SEND) ==
6608c2ecf20Sopenharmony_ci	    !!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) {
6618c2ecf20Sopenharmony_ci		rs485->flags |= SER_RS485_RTS_ON_SEND;
6628c2ecf20Sopenharmony_ci		rs485->flags &= ~SER_RS485_RTS_AFTER_SEND;
6638c2ecf20Sopenharmony_ci	}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	gpiod_set_value(port->rs485_term_gpio,
6668c2ecf20Sopenharmony_ci			rs485->flags & SER_RS485_TERMINATE_BUS);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	/*
6698c2ecf20Sopenharmony_ci	 * Both serial8250_em485_init() and serial8250_em485_destroy()
6708c2ecf20Sopenharmony_ci	 * are idempotent.
6718c2ecf20Sopenharmony_ci	 */
6728c2ecf20Sopenharmony_ci	if (rs485->flags & SER_RS485_ENABLED)
6738c2ecf20Sopenharmony_ci		return serial8250_em485_init(up);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	serial8250_em485_destroy(up);
6768c2ecf20Sopenharmony_ci	return 0;
6778c2ecf20Sopenharmony_ci}
6788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_em485_config);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci/*
6818c2ecf20Sopenharmony_ci * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
6828c2ecf20Sopenharmony_ci * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
6838c2ecf20Sopenharmony_ci * empty and the HW can idle again.
6848c2ecf20Sopenharmony_ci */
6858c2ecf20Sopenharmony_civoid serial8250_rpm_get_tx(struct uart_8250_port *p)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	unsigned char rpm_active;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (!(p->capabilities & UART_CAP_RPM))
6908c2ecf20Sopenharmony_ci		return;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	rpm_active = xchg(&p->rpm_tx_active, 1);
6938c2ecf20Sopenharmony_ci	if (rpm_active)
6948c2ecf20Sopenharmony_ci		return;
6958c2ecf20Sopenharmony_ci	pm_runtime_get_sync(p->port.dev);
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_rpm_get_tx);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_civoid serial8250_rpm_put_tx(struct uart_8250_port *p)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	unsigned char rpm_active;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	if (!(p->capabilities & UART_CAP_RPM))
7048c2ecf20Sopenharmony_ci		return;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	rpm_active = xchg(&p->rpm_tx_active, 0);
7078c2ecf20Sopenharmony_ci	if (!rpm_active)
7088c2ecf20Sopenharmony_ci		return;
7098c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(p->port.dev);
7108c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(p->port.dev);
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_rpm_put_tx);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci/*
7158c2ecf20Sopenharmony_ci * IER sleep support.  UARTs which have EFRs need the "extended
7168c2ecf20Sopenharmony_ci * capability" bit enabled.  Note that on XR16C850s, we need to
7178c2ecf20Sopenharmony_ci * reset LCR to write to IER.
7188c2ecf20Sopenharmony_ci */
7198c2ecf20Sopenharmony_cistatic void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	unsigned char lcr = 0, efr = 0;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	serial8250_rpm_get(p);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (p->capabilities & UART_CAP_SLEEP) {
7268c2ecf20Sopenharmony_ci		if (p->capabilities & UART_CAP_EFR) {
7278c2ecf20Sopenharmony_ci			lcr = serial_in(p, UART_LCR);
7288c2ecf20Sopenharmony_ci			efr = serial_in(p, UART_EFR);
7298c2ecf20Sopenharmony_ci			serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
7308c2ecf20Sopenharmony_ci			serial_out(p, UART_EFR, UART_EFR_ECB);
7318c2ecf20Sopenharmony_ci			serial_out(p, UART_LCR, 0);
7328c2ecf20Sopenharmony_ci		}
7338c2ecf20Sopenharmony_ci		serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
7348c2ecf20Sopenharmony_ci		if (p->capabilities & UART_CAP_EFR) {
7358c2ecf20Sopenharmony_ci			serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
7368c2ecf20Sopenharmony_ci			serial_out(p, UART_EFR, efr);
7378c2ecf20Sopenharmony_ci			serial_out(p, UART_LCR, lcr);
7388c2ecf20Sopenharmony_ci		}
7398c2ecf20Sopenharmony_ci	}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	serial8250_rpm_put(p);
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RSA
7458c2ecf20Sopenharmony_ci/*
7468c2ecf20Sopenharmony_ci * Attempts to turn on the RSA FIFO.  Returns zero on failure.
7478c2ecf20Sopenharmony_ci * We set the port uart clock rate if we succeed.
7488c2ecf20Sopenharmony_ci */
7498c2ecf20Sopenharmony_cistatic int __enable_rsa(struct uart_8250_port *up)
7508c2ecf20Sopenharmony_ci{
7518c2ecf20Sopenharmony_ci	unsigned char mode;
7528c2ecf20Sopenharmony_ci	int result;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	mode = serial_in(up, UART_RSA_MSR);
7558c2ecf20Sopenharmony_ci	result = mode & UART_RSA_MSR_FIFO;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	if (!result) {
7588c2ecf20Sopenharmony_ci		serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
7598c2ecf20Sopenharmony_ci		mode = serial_in(up, UART_RSA_MSR);
7608c2ecf20Sopenharmony_ci		result = mode & UART_RSA_MSR_FIFO;
7618c2ecf20Sopenharmony_ci	}
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	if (result)
7648c2ecf20Sopenharmony_ci		up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	return result;
7678c2ecf20Sopenharmony_ci}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistatic void enable_rsa(struct uart_8250_port *up)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	if (up->port.type == PORT_RSA) {
7728c2ecf20Sopenharmony_ci		if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
7738c2ecf20Sopenharmony_ci			spin_lock_irq(&up->port.lock);
7748c2ecf20Sopenharmony_ci			__enable_rsa(up);
7758c2ecf20Sopenharmony_ci			spin_unlock_irq(&up->port.lock);
7768c2ecf20Sopenharmony_ci		}
7778c2ecf20Sopenharmony_ci		if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
7788c2ecf20Sopenharmony_ci			serial_out(up, UART_RSA_FRR, 0);
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci/*
7838c2ecf20Sopenharmony_ci * Attempts to turn off the RSA FIFO.  Returns zero on failure.
7848c2ecf20Sopenharmony_ci * It is unknown why interrupts were disabled in here.  However,
7858c2ecf20Sopenharmony_ci * the caller is expected to preserve this behaviour by grabbing
7868c2ecf20Sopenharmony_ci * the spinlock before calling this function.
7878c2ecf20Sopenharmony_ci */
7888c2ecf20Sopenharmony_cistatic void disable_rsa(struct uart_8250_port *up)
7898c2ecf20Sopenharmony_ci{
7908c2ecf20Sopenharmony_ci	unsigned char mode;
7918c2ecf20Sopenharmony_ci	int result;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	if (up->port.type == PORT_RSA &&
7948c2ecf20Sopenharmony_ci	    up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
7958c2ecf20Sopenharmony_ci		spin_lock_irq(&up->port.lock);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci		mode = serial_in(up, UART_RSA_MSR);
7988c2ecf20Sopenharmony_ci		result = !(mode & UART_RSA_MSR_FIFO);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci		if (!result) {
8018c2ecf20Sopenharmony_ci			serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
8028c2ecf20Sopenharmony_ci			mode = serial_in(up, UART_RSA_MSR);
8038c2ecf20Sopenharmony_ci			result = !(mode & UART_RSA_MSR_FIFO);
8048c2ecf20Sopenharmony_ci		}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		if (result)
8078c2ecf20Sopenharmony_ci			up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
8088c2ecf20Sopenharmony_ci		spin_unlock_irq(&up->port.lock);
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci#endif /* CONFIG_SERIAL_8250_RSA */
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci/*
8148c2ecf20Sopenharmony_ci * This is a quickie test to see how big the FIFO is.
8158c2ecf20Sopenharmony_ci * It doesn't work at all the time, more's the pity.
8168c2ecf20Sopenharmony_ci */
8178c2ecf20Sopenharmony_cistatic int size_fifo(struct uart_8250_port *up)
8188c2ecf20Sopenharmony_ci{
8198c2ecf20Sopenharmony_ci	unsigned char old_fcr, old_mcr, old_lcr;
8208c2ecf20Sopenharmony_ci	unsigned short old_dl;
8218c2ecf20Sopenharmony_ci	int count;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	old_lcr = serial_in(up, UART_LCR);
8248c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0);
8258c2ecf20Sopenharmony_ci	old_fcr = serial_in(up, UART_FCR);
8268c2ecf20Sopenharmony_ci	old_mcr = serial8250_in_MCR(up);
8278c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
8288c2ecf20Sopenharmony_ci		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
8298c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, UART_MCR_LOOP);
8308c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
8318c2ecf20Sopenharmony_ci	old_dl = serial_dl_read(up);
8328c2ecf20Sopenharmony_ci	serial_dl_write(up, 0x0001);
8338c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0x03);
8348c2ecf20Sopenharmony_ci	for (count = 0; count < 256; count++)
8358c2ecf20Sopenharmony_ci		serial_out(up, UART_TX, count);
8368c2ecf20Sopenharmony_ci	mdelay(20);/* FIXME - schedule_timeout */
8378c2ecf20Sopenharmony_ci	for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
8388c2ecf20Sopenharmony_ci	     (count < 256); count++)
8398c2ecf20Sopenharmony_ci		serial_in(up, UART_RX);
8408c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, old_fcr);
8418c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, old_mcr);
8428c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
8438c2ecf20Sopenharmony_ci	serial_dl_write(up, old_dl);
8448c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, old_lcr);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	return count;
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci/*
8508c2ecf20Sopenharmony_ci * Read UART ID using the divisor method - set DLL and DLM to zero
8518c2ecf20Sopenharmony_ci * and the revision will be in DLL and device type in DLM.  We
8528c2ecf20Sopenharmony_ci * preserve the device state across this.
8538c2ecf20Sopenharmony_ci */
8548c2ecf20Sopenharmony_cistatic unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	unsigned char old_lcr;
8578c2ecf20Sopenharmony_ci	unsigned int id, old_dl;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	old_lcr = serial_in(p, UART_LCR);
8608c2ecf20Sopenharmony_ci	serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
8618c2ecf20Sopenharmony_ci	old_dl = serial_dl_read(p);
8628c2ecf20Sopenharmony_ci	serial_dl_write(p, 0);
8638c2ecf20Sopenharmony_ci	id = serial_dl_read(p);
8648c2ecf20Sopenharmony_ci	serial_dl_write(p, old_dl);
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	serial_out(p, UART_LCR, old_lcr);
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	return id;
8698c2ecf20Sopenharmony_ci}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci/*
8728c2ecf20Sopenharmony_ci * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
8738c2ecf20Sopenharmony_ci * When this function is called we know it is at least a StarTech
8748c2ecf20Sopenharmony_ci * 16650 V2, but it might be one of several StarTech UARTs, or one of
8758c2ecf20Sopenharmony_ci * its clones.  (We treat the broken original StarTech 16650 V1 as a
8768c2ecf20Sopenharmony_ci * 16550, and why not?  Startech doesn't seem to even acknowledge its
8778c2ecf20Sopenharmony_ci * existence.)
8788c2ecf20Sopenharmony_ci *
8798c2ecf20Sopenharmony_ci * What evil have men's minds wrought...
8808c2ecf20Sopenharmony_ci */
8818c2ecf20Sopenharmony_cistatic void autoconfig_has_efr(struct uart_8250_port *up)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	unsigned int id1, id2, id3, rev;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	/*
8868c2ecf20Sopenharmony_ci	 * Everything with an EFR has SLEEP
8878c2ecf20Sopenharmony_ci	 */
8888c2ecf20Sopenharmony_ci	up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	/*
8918c2ecf20Sopenharmony_ci	 * First we check to see if it's an Oxford Semiconductor UART.
8928c2ecf20Sopenharmony_ci	 *
8938c2ecf20Sopenharmony_ci	 * If we have to do this here because some non-National
8948c2ecf20Sopenharmony_ci	 * Semiconductor clone chips lock up if you try writing to the
8958c2ecf20Sopenharmony_ci	 * LSR register (which serial_icr_read does)
8968c2ecf20Sopenharmony_ci	 */
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	/*
8998c2ecf20Sopenharmony_ci	 * Check for Oxford Semiconductor 16C950.
9008c2ecf20Sopenharmony_ci	 *
9018c2ecf20Sopenharmony_ci	 * EFR [4] must be set else this test fails.
9028c2ecf20Sopenharmony_ci	 *
9038c2ecf20Sopenharmony_ci	 * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
9048c2ecf20Sopenharmony_ci	 * claims that it's needed for 952 dual UART's (which are not
9058c2ecf20Sopenharmony_ci	 * recommended for new designs).
9068c2ecf20Sopenharmony_ci	 */
9078c2ecf20Sopenharmony_ci	up->acr = 0;
9088c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
9098c2ecf20Sopenharmony_ci	serial_out(up, UART_EFR, UART_EFR_ECB);
9108c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0x00);
9118c2ecf20Sopenharmony_ci	id1 = serial_icr_read(up, UART_ID1);
9128c2ecf20Sopenharmony_ci	id2 = serial_icr_read(up, UART_ID2);
9138c2ecf20Sopenharmony_ci	id3 = serial_icr_read(up, UART_ID3);
9148c2ecf20Sopenharmony_ci	rev = serial_icr_read(up, UART_REV);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	if (id1 == 0x16 && id2 == 0xC9 &&
9198c2ecf20Sopenharmony_ci	    (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
9208c2ecf20Sopenharmony_ci		up->port.type = PORT_16C950;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		/*
9238c2ecf20Sopenharmony_ci		 * Enable work around for the Oxford Semiconductor 952 rev B
9248c2ecf20Sopenharmony_ci		 * chip which causes it to seriously miscalculate baud rates
9258c2ecf20Sopenharmony_ci		 * when DLL is 0.
9268c2ecf20Sopenharmony_ci		 */
9278c2ecf20Sopenharmony_ci		if (id3 == 0x52 && rev == 0x01)
9288c2ecf20Sopenharmony_ci			up->bugs |= UART_BUG_QUOT;
9298c2ecf20Sopenharmony_ci		return;
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	/*
9338c2ecf20Sopenharmony_ci	 * We check for a XR16C850 by setting DLL and DLM to 0, and then
9348c2ecf20Sopenharmony_ci	 * reading back DLL and DLM.  The chip type depends on the DLM
9358c2ecf20Sopenharmony_ci	 * value read back:
9368c2ecf20Sopenharmony_ci	 *  0x10 - XR16C850 and the DLL contains the chip revision.
9378c2ecf20Sopenharmony_ci	 *  0x12 - XR16C2850.
9388c2ecf20Sopenharmony_ci	 *  0x14 - XR16C854.
9398c2ecf20Sopenharmony_ci	 */
9408c2ecf20Sopenharmony_ci	id1 = autoconfig_read_divisor_id(up);
9418c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("850id=%04x ", id1);
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	id2 = id1 >> 8;
9448c2ecf20Sopenharmony_ci	if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
9458c2ecf20Sopenharmony_ci		up->port.type = PORT_16850;
9468c2ecf20Sopenharmony_ci		return;
9478c2ecf20Sopenharmony_ci	}
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	/*
9508c2ecf20Sopenharmony_ci	 * It wasn't an XR16C850.
9518c2ecf20Sopenharmony_ci	 *
9528c2ecf20Sopenharmony_ci	 * We distinguish between the '654 and the '650 by counting
9538c2ecf20Sopenharmony_ci	 * how many bytes are in the FIFO.  I'm using this for now,
9548c2ecf20Sopenharmony_ci	 * since that's the technique that was sent to me in the
9558c2ecf20Sopenharmony_ci	 * serial driver update, but I'm not convinced this works.
9568c2ecf20Sopenharmony_ci	 * I've had problems doing this in the past.  -TYT
9578c2ecf20Sopenharmony_ci	 */
9588c2ecf20Sopenharmony_ci	if (size_fifo(up) == 64)
9598c2ecf20Sopenharmony_ci		up->port.type = PORT_16654;
9608c2ecf20Sopenharmony_ci	else
9618c2ecf20Sopenharmony_ci		up->port.type = PORT_16650V2;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci/*
9658c2ecf20Sopenharmony_ci * We detected a chip without a FIFO.  Only two fall into
9668c2ecf20Sopenharmony_ci * this category - the original 8250 and the 16450.  The
9678c2ecf20Sopenharmony_ci * 16450 has a scratch register (accessible with LCR=0)
9688c2ecf20Sopenharmony_ci */
9698c2ecf20Sopenharmony_cistatic void autoconfig_8250(struct uart_8250_port *up)
9708c2ecf20Sopenharmony_ci{
9718c2ecf20Sopenharmony_ci	unsigned char scratch, status1, status2;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	up->port.type = PORT_8250;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	scratch = serial_in(up, UART_SCR);
9768c2ecf20Sopenharmony_ci	serial_out(up, UART_SCR, 0xa5);
9778c2ecf20Sopenharmony_ci	status1 = serial_in(up, UART_SCR);
9788c2ecf20Sopenharmony_ci	serial_out(up, UART_SCR, 0x5a);
9798c2ecf20Sopenharmony_ci	status2 = serial_in(up, UART_SCR);
9808c2ecf20Sopenharmony_ci	serial_out(up, UART_SCR, scratch);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	if (status1 == 0xa5 && status2 == 0x5a)
9838c2ecf20Sopenharmony_ci		up->port.type = PORT_16450;
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_cistatic int broken_efr(struct uart_8250_port *up)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	/*
9898c2ecf20Sopenharmony_ci	 * Exar ST16C2550 "A2" devices incorrectly detect as
9908c2ecf20Sopenharmony_ci	 * having an EFR, and report an ID of 0x0201.  See
9918c2ecf20Sopenharmony_ci	 * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
9928c2ecf20Sopenharmony_ci	 */
9938c2ecf20Sopenharmony_ci	if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
9948c2ecf20Sopenharmony_ci		return 1;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	return 0;
9978c2ecf20Sopenharmony_ci}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci/*
10008c2ecf20Sopenharmony_ci * We know that the chip has FIFOs.  Does it have an EFR?  The
10018c2ecf20Sopenharmony_ci * EFR is located in the same register position as the IIR and
10028c2ecf20Sopenharmony_ci * we know the top two bits of the IIR are currently set.  The
10038c2ecf20Sopenharmony_ci * EFR should contain zero.  Try to read the EFR.
10048c2ecf20Sopenharmony_ci */
10058c2ecf20Sopenharmony_cistatic void autoconfig_16550a(struct uart_8250_port *up)
10068c2ecf20Sopenharmony_ci{
10078c2ecf20Sopenharmony_ci	unsigned char status1, status2;
10088c2ecf20Sopenharmony_ci	unsigned int iersave;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	up->port.type = PORT_16550A;
10118c2ecf20Sopenharmony_ci	up->capabilities |= UART_CAP_FIFO;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (!IS_ENABLED(CONFIG_SERIAL_8250_16550A_VARIANTS) &&
10148c2ecf20Sopenharmony_ci	    !(up->port.flags & UPF_FULL_PROBE))
10158c2ecf20Sopenharmony_ci		return;
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	/*
10188c2ecf20Sopenharmony_ci	 * Check for presence of the EFR when DLAB is set.
10198c2ecf20Sopenharmony_ci	 * Only ST16C650V1 UARTs pass this test.
10208c2ecf20Sopenharmony_ci	 */
10218c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
10228c2ecf20Sopenharmony_ci	if (serial_in(up, UART_EFR) == 0) {
10238c2ecf20Sopenharmony_ci		serial_out(up, UART_EFR, 0xA8);
10248c2ecf20Sopenharmony_ci		if (serial_in(up, UART_EFR) != 0) {
10258c2ecf20Sopenharmony_ci			DEBUG_AUTOCONF("EFRv1 ");
10268c2ecf20Sopenharmony_ci			up->port.type = PORT_16650;
10278c2ecf20Sopenharmony_ci			up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
10288c2ecf20Sopenharmony_ci		} else {
10298c2ecf20Sopenharmony_ci			serial_out(up, UART_LCR, 0);
10308c2ecf20Sopenharmony_ci			serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
10318c2ecf20Sopenharmony_ci				   UART_FCR7_64BYTE);
10328c2ecf20Sopenharmony_ci			status1 = serial_in(up, UART_IIR) >> 5;
10338c2ecf20Sopenharmony_ci			serial_out(up, UART_FCR, 0);
10348c2ecf20Sopenharmony_ci			serial_out(up, UART_LCR, 0);
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci			if (status1 == 7)
10378c2ecf20Sopenharmony_ci				up->port.type = PORT_16550A_FSL64;
10388c2ecf20Sopenharmony_ci			else
10398c2ecf20Sopenharmony_ci				DEBUG_AUTOCONF("Motorola 8xxx DUART ");
10408c2ecf20Sopenharmony_ci		}
10418c2ecf20Sopenharmony_ci		serial_out(up, UART_EFR, 0);
10428c2ecf20Sopenharmony_ci		return;
10438c2ecf20Sopenharmony_ci	}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	/*
10468c2ecf20Sopenharmony_ci	 * Maybe it requires 0xbf to be written to the LCR.
10478c2ecf20Sopenharmony_ci	 * (other ST16C650V2 UARTs, TI16C752A, etc)
10488c2ecf20Sopenharmony_ci	 */
10498c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
10508c2ecf20Sopenharmony_ci	if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
10518c2ecf20Sopenharmony_ci		DEBUG_AUTOCONF("EFRv2 ");
10528c2ecf20Sopenharmony_ci		autoconfig_has_efr(up);
10538c2ecf20Sopenharmony_ci		return;
10548c2ecf20Sopenharmony_ci	}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	/*
10578c2ecf20Sopenharmony_ci	 * Check for a National Semiconductor SuperIO chip.
10588c2ecf20Sopenharmony_ci	 * Attempt to switch to bank 2, read the value of the LOOP bit
10598c2ecf20Sopenharmony_ci	 * from EXCR1. Switch back to bank 0, change it in MCR. Then
10608c2ecf20Sopenharmony_ci	 * switch back to bank 2, read it from EXCR1 again and check
10618c2ecf20Sopenharmony_ci	 * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
10628c2ecf20Sopenharmony_ci	 */
10638c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0);
10648c2ecf20Sopenharmony_ci	status1 = serial8250_in_MCR(up);
10658c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0xE0);
10668c2ecf20Sopenharmony_ci	status2 = serial_in(up, 0x02); /* EXCR1 */
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	if (!((status2 ^ status1) & UART_MCR_LOOP)) {
10698c2ecf20Sopenharmony_ci		serial_out(up, UART_LCR, 0);
10708c2ecf20Sopenharmony_ci		serial8250_out_MCR(up, status1 ^ UART_MCR_LOOP);
10718c2ecf20Sopenharmony_ci		serial_out(up, UART_LCR, 0xE0);
10728c2ecf20Sopenharmony_ci		status2 = serial_in(up, 0x02); /* EXCR1 */
10738c2ecf20Sopenharmony_ci		serial_out(up, UART_LCR, 0);
10748c2ecf20Sopenharmony_ci		serial8250_out_MCR(up, status1);
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		if ((status2 ^ status1) & UART_MCR_LOOP) {
10778c2ecf20Sopenharmony_ci			unsigned short quot;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci			serial_out(up, UART_LCR, 0xE0);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci			quot = serial_dl_read(up);
10828c2ecf20Sopenharmony_ci			quot <<= 3;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci			if (ns16550a_goto_highspeed(up))
10858c2ecf20Sopenharmony_ci				serial_dl_write(up, quot);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci			serial_out(up, UART_LCR, 0);
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci			up->port.uartclk = 921600*16;
10908c2ecf20Sopenharmony_ci			up->port.type = PORT_NS16550A;
10918c2ecf20Sopenharmony_ci			up->capabilities |= UART_NATSEMI;
10928c2ecf20Sopenharmony_ci			return;
10938c2ecf20Sopenharmony_ci		}
10948c2ecf20Sopenharmony_ci	}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	/*
10978c2ecf20Sopenharmony_ci	 * No EFR.  Try to detect a TI16750, which only sets bit 5 of
10988c2ecf20Sopenharmony_ci	 * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
10998c2ecf20Sopenharmony_ci	 * Try setting it with and without DLAB set.  Cheap clones
11008c2ecf20Sopenharmony_ci	 * set bit 5 without DLAB set.
11018c2ecf20Sopenharmony_ci	 */
11028c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0);
11038c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
11048c2ecf20Sopenharmony_ci	status1 = serial_in(up, UART_IIR) >> 5;
11058c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
11068c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
11078c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
11088c2ecf20Sopenharmony_ci	status2 = serial_in(up, UART_IIR) >> 5;
11098c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
11108c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0);
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	if (status1 == 6 && status2 == 7) {
11158c2ecf20Sopenharmony_ci		up->port.type = PORT_16750;
11168c2ecf20Sopenharmony_ci		up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
11178c2ecf20Sopenharmony_ci		return;
11188c2ecf20Sopenharmony_ci	}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	/*
11218c2ecf20Sopenharmony_ci	 * Try writing and reading the UART_IER_UUE bit (b6).
11228c2ecf20Sopenharmony_ci	 * If it works, this is probably one of the Xscale platform's
11238c2ecf20Sopenharmony_ci	 * internal UARTs.
11248c2ecf20Sopenharmony_ci	 * We're going to explicitly set the UUE bit to 0 before
11258c2ecf20Sopenharmony_ci	 * trying to write and read a 1 just to make sure it's not
11268c2ecf20Sopenharmony_ci	 * already a 1 and maybe locked there before we even start start.
11278c2ecf20Sopenharmony_ci	 */
11288c2ecf20Sopenharmony_ci	iersave = serial_in(up, UART_IER);
11298c2ecf20Sopenharmony_ci	serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
11308c2ecf20Sopenharmony_ci	if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
11318c2ecf20Sopenharmony_ci		/*
11328c2ecf20Sopenharmony_ci		 * OK it's in a known zero state, try writing and reading
11338c2ecf20Sopenharmony_ci		 * without disturbing the current state of the other bits.
11348c2ecf20Sopenharmony_ci		 */
11358c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, iersave | UART_IER_UUE);
11368c2ecf20Sopenharmony_ci		if (serial_in(up, UART_IER) & UART_IER_UUE) {
11378c2ecf20Sopenharmony_ci			/*
11388c2ecf20Sopenharmony_ci			 * It's an Xscale.
11398c2ecf20Sopenharmony_ci			 * We'll leave the UART_IER_UUE bit set to 1 (enabled).
11408c2ecf20Sopenharmony_ci			 */
11418c2ecf20Sopenharmony_ci			DEBUG_AUTOCONF("Xscale ");
11428c2ecf20Sopenharmony_ci			up->port.type = PORT_XSCALE;
11438c2ecf20Sopenharmony_ci			up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
11448c2ecf20Sopenharmony_ci			return;
11458c2ecf20Sopenharmony_ci		}
11468c2ecf20Sopenharmony_ci	} else {
11478c2ecf20Sopenharmony_ci		/*
11488c2ecf20Sopenharmony_ci		 * If we got here we couldn't force the IER_UUE bit to 0.
11498c2ecf20Sopenharmony_ci		 * Log it and continue.
11508c2ecf20Sopenharmony_ci		 */
11518c2ecf20Sopenharmony_ci		DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci	serial_out(up, UART_IER, iersave);
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	/*
11568c2ecf20Sopenharmony_ci	 * We distinguish between 16550A and U6 16550A by counting
11578c2ecf20Sopenharmony_ci	 * how many bytes are in the FIFO.
11588c2ecf20Sopenharmony_ci	 */
11598c2ecf20Sopenharmony_ci	if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
11608c2ecf20Sopenharmony_ci		up->port.type = PORT_U6_16550A;
11618c2ecf20Sopenharmony_ci		up->capabilities |= UART_CAP_AFE;
11628c2ecf20Sopenharmony_ci	}
11638c2ecf20Sopenharmony_ci}
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci/*
11668c2ecf20Sopenharmony_ci * This routine is called by rs_init() to initialize a specific serial
11678c2ecf20Sopenharmony_ci * port.  It determines what type of UART chip this serial port is
11688c2ecf20Sopenharmony_ci * using: 8250, 16450, 16550, 16550A.  The important question is
11698c2ecf20Sopenharmony_ci * whether or not this UART is a 16550A or not, since this will
11708c2ecf20Sopenharmony_ci * determine whether or not we can use its FIFO features or not.
11718c2ecf20Sopenharmony_ci */
11728c2ecf20Sopenharmony_cistatic void autoconfig(struct uart_8250_port *up)
11738c2ecf20Sopenharmony_ci{
11748c2ecf20Sopenharmony_ci	unsigned char status1, scratch, scratch2, scratch3;
11758c2ecf20Sopenharmony_ci	unsigned char save_lcr, save_mcr;
11768c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
11778c2ecf20Sopenharmony_ci	unsigned long flags;
11788c2ecf20Sopenharmony_ci	unsigned int old_capabilities;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	if (!port->iobase && !port->mapbase && !port->membase)
11818c2ecf20Sopenharmony_ci		return;
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("%s: autoconf (0x%04lx, 0x%p): ",
11848c2ecf20Sopenharmony_ci		       port->name, port->iobase, port->membase);
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	/*
11878c2ecf20Sopenharmony_ci	 * We really do need global IRQs disabled here - we're going to
11888c2ecf20Sopenharmony_ci	 * be frobbing the chips IRQ enable register to see if it exists.
11898c2ecf20Sopenharmony_ci	 */
11908c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	up->capabilities = 0;
11938c2ecf20Sopenharmony_ci	up->bugs = 0;
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	if (!(port->flags & UPF_BUGGY_UART)) {
11968c2ecf20Sopenharmony_ci		/*
11978c2ecf20Sopenharmony_ci		 * Do a simple existence test first; if we fail this,
11988c2ecf20Sopenharmony_ci		 * there's no point trying anything else.
11998c2ecf20Sopenharmony_ci		 *
12008c2ecf20Sopenharmony_ci		 * 0x80 is used as a nonsense port to prevent against
12018c2ecf20Sopenharmony_ci		 * false positives due to ISA bus float.  The
12028c2ecf20Sopenharmony_ci		 * assumption is that 0x80 is a non-existent port;
12038c2ecf20Sopenharmony_ci		 * which should be safe since include/asm/io.h also
12048c2ecf20Sopenharmony_ci		 * makes this assumption.
12058c2ecf20Sopenharmony_ci		 *
12068c2ecf20Sopenharmony_ci		 * Note: this is safe as long as MCR bit 4 is clear
12078c2ecf20Sopenharmony_ci		 * and the device is in "PC" mode.
12088c2ecf20Sopenharmony_ci		 */
12098c2ecf20Sopenharmony_ci		scratch = serial_in(up, UART_IER);
12108c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, 0);
12118c2ecf20Sopenharmony_ci#ifdef __i386__
12128c2ecf20Sopenharmony_ci		outb(0xff, 0x080);
12138c2ecf20Sopenharmony_ci#endif
12148c2ecf20Sopenharmony_ci		/*
12158c2ecf20Sopenharmony_ci		 * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
12168c2ecf20Sopenharmony_ci		 * 16C754B) allow only to modify them if an EFR bit is set.
12178c2ecf20Sopenharmony_ci		 */
12188c2ecf20Sopenharmony_ci		scratch2 = serial_in(up, UART_IER) & 0x0f;
12198c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, 0x0F);
12208c2ecf20Sopenharmony_ci#ifdef __i386__
12218c2ecf20Sopenharmony_ci		outb(0, 0x080);
12228c2ecf20Sopenharmony_ci#endif
12238c2ecf20Sopenharmony_ci		scratch3 = serial_in(up, UART_IER) & 0x0f;
12248c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, scratch);
12258c2ecf20Sopenharmony_ci		if (scratch2 != 0 || scratch3 != 0x0F) {
12268c2ecf20Sopenharmony_ci			/*
12278c2ecf20Sopenharmony_ci			 * We failed; there's nothing here
12288c2ecf20Sopenharmony_ci			 */
12298c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&port->lock, flags);
12308c2ecf20Sopenharmony_ci			DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
12318c2ecf20Sopenharmony_ci				       scratch2, scratch3);
12328c2ecf20Sopenharmony_ci			goto out;
12338c2ecf20Sopenharmony_ci		}
12348c2ecf20Sopenharmony_ci	}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	save_mcr = serial8250_in_MCR(up);
12378c2ecf20Sopenharmony_ci	save_lcr = serial_in(up, UART_LCR);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	/*
12408c2ecf20Sopenharmony_ci	 * Check to see if a UART is really there.  Certain broken
12418c2ecf20Sopenharmony_ci	 * internal modems based on the Rockwell chipset fail this
12428c2ecf20Sopenharmony_ci	 * test, because they apparently don't implement the loopback
12438c2ecf20Sopenharmony_ci	 * test mode.  So this test is skipped on the COM 1 through
12448c2ecf20Sopenharmony_ci	 * COM 4 ports.  This *should* be safe, since no board
12458c2ecf20Sopenharmony_ci	 * manufacturer would be stupid enough to design a board
12468c2ecf20Sopenharmony_ci	 * that conflicts with COM 1-4 --- we hope!
12478c2ecf20Sopenharmony_ci	 */
12488c2ecf20Sopenharmony_ci	if (!(port->flags & UPF_SKIP_TEST)) {
12498c2ecf20Sopenharmony_ci		serial8250_out_MCR(up, UART_MCR_LOOP | 0x0A);
12508c2ecf20Sopenharmony_ci		status1 = serial_in(up, UART_MSR) & 0xF0;
12518c2ecf20Sopenharmony_ci		serial8250_out_MCR(up, save_mcr);
12528c2ecf20Sopenharmony_ci		if (status1 != 0x90) {
12538c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&port->lock, flags);
12548c2ecf20Sopenharmony_ci			DEBUG_AUTOCONF("LOOP test failed (%02x) ",
12558c2ecf20Sopenharmony_ci				       status1);
12568c2ecf20Sopenharmony_ci			goto out;
12578c2ecf20Sopenharmony_ci		}
12588c2ecf20Sopenharmony_ci	}
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	/*
12618c2ecf20Sopenharmony_ci	 * We're pretty sure there's a port here.  Lets find out what
12628c2ecf20Sopenharmony_ci	 * type of port it is.  The IIR top two bits allows us to find
12638c2ecf20Sopenharmony_ci	 * out if it's 8250 or 16450, 16550, 16550A or later.  This
12648c2ecf20Sopenharmony_ci	 * determines what we test for next.
12658c2ecf20Sopenharmony_ci	 *
12668c2ecf20Sopenharmony_ci	 * We also initialise the EFR (if any) to zero for later.  The
12678c2ecf20Sopenharmony_ci	 * EFR occupies the same register location as the FCR and IIR.
12688c2ecf20Sopenharmony_ci	 */
12698c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
12708c2ecf20Sopenharmony_ci	serial_out(up, UART_EFR, 0);
12718c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, 0);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	/* Assign this as it is to truncate any bits above 7.  */
12768c2ecf20Sopenharmony_ci	scratch = serial_in(up, UART_IIR);
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	switch (scratch >> 6) {
12798c2ecf20Sopenharmony_ci	case 0:
12808c2ecf20Sopenharmony_ci		autoconfig_8250(up);
12818c2ecf20Sopenharmony_ci		break;
12828c2ecf20Sopenharmony_ci	case 1:
12838c2ecf20Sopenharmony_ci		port->type = PORT_UNKNOWN;
12848c2ecf20Sopenharmony_ci		break;
12858c2ecf20Sopenharmony_ci	case 2:
12868c2ecf20Sopenharmony_ci		port->type = PORT_16550;
12878c2ecf20Sopenharmony_ci		break;
12888c2ecf20Sopenharmony_ci	case 3:
12898c2ecf20Sopenharmony_ci		autoconfig_16550a(up);
12908c2ecf20Sopenharmony_ci		break;
12918c2ecf20Sopenharmony_ci	}
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RSA
12948c2ecf20Sopenharmony_ci	/*
12958c2ecf20Sopenharmony_ci	 * Only probe for RSA ports if we got the region.
12968c2ecf20Sopenharmony_ci	 */
12978c2ecf20Sopenharmony_ci	if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
12988c2ecf20Sopenharmony_ci	    __enable_rsa(up))
12998c2ecf20Sopenharmony_ci		port->type = PORT_RSA;
13008c2ecf20Sopenharmony_ci#endif
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	serial_out(up, UART_LCR, save_lcr);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	port->fifosize = uart_config[up->port.type].fifo_size;
13058c2ecf20Sopenharmony_ci	old_capabilities = up->capabilities;
13068c2ecf20Sopenharmony_ci	up->capabilities = uart_config[port->type].flags;
13078c2ecf20Sopenharmony_ci	up->tx_loadsz = uart_config[port->type].tx_loadsz;
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	if (port->type == PORT_UNKNOWN)
13108c2ecf20Sopenharmony_ci		goto out_lock;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	/*
13138c2ecf20Sopenharmony_ci	 * Reset the UART.
13148c2ecf20Sopenharmony_ci	 */
13158c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RSA
13168c2ecf20Sopenharmony_ci	if (port->type == PORT_RSA)
13178c2ecf20Sopenharmony_ci		serial_out(up, UART_RSA_FRR, 0);
13188c2ecf20Sopenharmony_ci#endif
13198c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, save_mcr);
13208c2ecf20Sopenharmony_ci	serial8250_clear_fifos(up);
13218c2ecf20Sopenharmony_ci	serial_in(up, UART_RX);
13228c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_UUE)
13238c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, UART_IER_UUE);
13248c2ecf20Sopenharmony_ci	else
13258c2ecf20Sopenharmony_ci		serial_out(up, UART_IER, 0);
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ciout_lock:
13288c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	/*
13318c2ecf20Sopenharmony_ci	 * Check if the device is a Fintek F81216A
13328c2ecf20Sopenharmony_ci	 */
13338c2ecf20Sopenharmony_ci	if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
13348c2ecf20Sopenharmony_ci		fintek_8250_probe(up);
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	if (up->capabilities != old_capabilities) {
13378c2ecf20Sopenharmony_ci		dev_warn(port->dev, "detected caps %08x should be %08x\n",
13388c2ecf20Sopenharmony_ci			 old_capabilities, up->capabilities);
13398c2ecf20Sopenharmony_ci	}
13408c2ecf20Sopenharmony_ciout:
13418c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("iir=%d ", scratch);
13428c2ecf20Sopenharmony_ci	DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
13438c2ecf20Sopenharmony_ci}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_cistatic void autoconfig_irq(struct uart_8250_port *up)
13468c2ecf20Sopenharmony_ci{
13478c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
13488c2ecf20Sopenharmony_ci	unsigned char save_mcr, save_ier;
13498c2ecf20Sopenharmony_ci	unsigned char save_ICP = 0;
13508c2ecf20Sopenharmony_ci	unsigned int ICP = 0;
13518c2ecf20Sopenharmony_ci	unsigned long irqs;
13528c2ecf20Sopenharmony_ci	int irq;
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	if (port->flags & UPF_FOURPORT) {
13558c2ecf20Sopenharmony_ci		ICP = (port->iobase & 0xfe0) | 0x1f;
13568c2ecf20Sopenharmony_ci		save_ICP = inb_p(ICP);
13578c2ecf20Sopenharmony_ci		outb_p(0x80, ICP);
13588c2ecf20Sopenharmony_ci		inb_p(ICP);
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	if (uart_console(port))
13628c2ecf20Sopenharmony_ci		console_lock();
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	/* forget possible initially masked and pending IRQ */
13658c2ecf20Sopenharmony_ci	probe_irq_off(probe_irq_on());
13668c2ecf20Sopenharmony_ci	save_mcr = serial8250_in_MCR(up);
13678c2ecf20Sopenharmony_ci	save_ier = serial_in(up, UART_IER);
13688c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2);
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	irqs = probe_irq_on();
13718c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, 0);
13728c2ecf20Sopenharmony_ci	udelay(10);
13738c2ecf20Sopenharmony_ci	if (port->flags & UPF_FOURPORT) {
13748c2ecf20Sopenharmony_ci		serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
13758c2ecf20Sopenharmony_ci	} else {
13768c2ecf20Sopenharmony_ci		serial8250_out_MCR(up,
13778c2ecf20Sopenharmony_ci			UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
13788c2ecf20Sopenharmony_ci	}
13798c2ecf20Sopenharmony_ci	serial_out(up, UART_IER, 0x0f);	/* enable all intrs */
13808c2ecf20Sopenharmony_ci	serial_in(up, UART_LSR);
13818c2ecf20Sopenharmony_ci	serial_in(up, UART_RX);
13828c2ecf20Sopenharmony_ci	serial_in(up, UART_IIR);
13838c2ecf20Sopenharmony_ci	serial_in(up, UART_MSR);
13848c2ecf20Sopenharmony_ci	serial_out(up, UART_TX, 0xFF);
13858c2ecf20Sopenharmony_ci	udelay(20);
13868c2ecf20Sopenharmony_ci	irq = probe_irq_off(irqs);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, save_mcr);
13898c2ecf20Sopenharmony_ci	serial_out(up, UART_IER, save_ier);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	if (port->flags & UPF_FOURPORT)
13928c2ecf20Sopenharmony_ci		outb_p(save_ICP, ICP);
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	if (uart_console(port))
13958c2ecf20Sopenharmony_ci		console_unlock();
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci	port->irq = (irq > 0) ? irq : 0;
13988c2ecf20Sopenharmony_ci}
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_cistatic void serial8250_stop_rx(struct uart_port *port)
14018c2ecf20Sopenharmony_ci{
14028c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
14078c2ecf20Sopenharmony_ci	up->port.read_status_mask &= ~UART_LSR_DR;
14088c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, up->ier);
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci/**
14148c2ecf20Sopenharmony_ci * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback
14158c2ecf20Sopenharmony_ci * @p: uart 8250 port
14168c2ecf20Sopenharmony_ci *
14178c2ecf20Sopenharmony_ci * Generic callback usable by 8250 uart drivers to stop rs485 transmission.
14188c2ecf20Sopenharmony_ci */
14198c2ecf20Sopenharmony_civoid serial8250_em485_stop_tx(struct uart_8250_port *p)
14208c2ecf20Sopenharmony_ci{
14218c2ecf20Sopenharmony_ci	unsigned char mcr = serial8250_in_MCR(p);
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
14248c2ecf20Sopenharmony_ci		mcr |= UART_MCR_RTS;
14258c2ecf20Sopenharmony_ci	else
14268c2ecf20Sopenharmony_ci		mcr &= ~UART_MCR_RTS;
14278c2ecf20Sopenharmony_ci	serial8250_out_MCR(p, mcr);
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	/*
14308c2ecf20Sopenharmony_ci	 * Empty the RX FIFO, we are not interested in anything
14318c2ecf20Sopenharmony_ci	 * received during the half-duplex transmission.
14328c2ecf20Sopenharmony_ci	 * Enable previously disabled RX interrupts.
14338c2ecf20Sopenharmony_ci	 */
14348c2ecf20Sopenharmony_ci	if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
14358c2ecf20Sopenharmony_ci		serial8250_clear_and_reinit_fifos(p);
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci		p->ier |= UART_IER_RLSI | UART_IER_RDI;
14388c2ecf20Sopenharmony_ci		serial_port_out(&p->port, UART_IER, p->ier);
14398c2ecf20Sopenharmony_ci	}
14408c2ecf20Sopenharmony_ci}
14418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_cistatic enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
14448c2ecf20Sopenharmony_ci{
14458c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485;
14468c2ecf20Sopenharmony_ci	struct uart_8250_port *p;
14478c2ecf20Sopenharmony_ci	unsigned long flags;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	em485 = container_of(t, struct uart_8250_em485, stop_tx_timer);
14508c2ecf20Sopenharmony_ci	p = em485->port;
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	serial8250_rpm_get(p);
14538c2ecf20Sopenharmony_ci	spin_lock_irqsave(&p->port.lock, flags);
14548c2ecf20Sopenharmony_ci	if (em485->active_timer == &em485->stop_tx_timer) {
14558c2ecf20Sopenharmony_ci		p->rs485_stop_tx(p);
14568c2ecf20Sopenharmony_ci		em485->active_timer = NULL;
14578c2ecf20Sopenharmony_ci		em485->tx_stopped = true;
14588c2ecf20Sopenharmony_ci	}
14598c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&p->port.lock, flags);
14608c2ecf20Sopenharmony_ci	serial8250_rpm_put(p);
14618c2ecf20Sopenharmony_ci	return HRTIMER_NORESTART;
14628c2ecf20Sopenharmony_ci}
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_cistatic void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
14658c2ecf20Sopenharmony_ci{
14668c2ecf20Sopenharmony_ci	long sec = msec / 1000;
14678c2ecf20Sopenharmony_ci	long nsec = (msec % 1000) * 1000000;
14688c2ecf20Sopenharmony_ci	ktime_t t = ktime_set(sec, nsec);
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	hrtimer_start(hrt, t, HRTIMER_MODE_REL);
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic void __stop_tx_rs485(struct uart_8250_port *p)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485 = p->em485;
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	/*
14788c2ecf20Sopenharmony_ci	 * rs485_stop_tx() is going to set RTS according to config
14798c2ecf20Sopenharmony_ci	 * AND flush RX FIFO if required.
14808c2ecf20Sopenharmony_ci	 */
14818c2ecf20Sopenharmony_ci	if (p->port.rs485.delay_rts_after_send > 0) {
14828c2ecf20Sopenharmony_ci		em485->active_timer = &em485->stop_tx_timer;
14838c2ecf20Sopenharmony_ci		start_hrtimer_ms(&em485->stop_tx_timer,
14848c2ecf20Sopenharmony_ci				   p->port.rs485.delay_rts_after_send);
14858c2ecf20Sopenharmony_ci	} else {
14868c2ecf20Sopenharmony_ci		p->rs485_stop_tx(p);
14878c2ecf20Sopenharmony_ci		em485->active_timer = NULL;
14888c2ecf20Sopenharmony_ci		em485->tx_stopped = true;
14898c2ecf20Sopenharmony_ci	}
14908c2ecf20Sopenharmony_ci}
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_cistatic inline void __do_stop_tx(struct uart_8250_port *p)
14938c2ecf20Sopenharmony_ci{
14948c2ecf20Sopenharmony_ci	if (serial8250_clear_THRI(p))
14958c2ecf20Sopenharmony_ci		serial8250_rpm_put_tx(p);
14968c2ecf20Sopenharmony_ci}
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_cistatic inline void __stop_tx(struct uart_8250_port *p)
14998c2ecf20Sopenharmony_ci{
15008c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485 = p->em485;
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	if (em485) {
15038c2ecf20Sopenharmony_ci		unsigned char lsr = serial_in(p, UART_LSR);
15048c2ecf20Sopenharmony_ci		p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci		/*
15078c2ecf20Sopenharmony_ci		 * To provide required timeing and allow FIFO transfer,
15088c2ecf20Sopenharmony_ci		 * __stop_tx_rs485() must be called only when both FIFO and
15098c2ecf20Sopenharmony_ci		 * shift register are empty. It is for device driver to enable
15108c2ecf20Sopenharmony_ci		 * interrupt on TEMT.
15118c2ecf20Sopenharmony_ci		 */
15128c2ecf20Sopenharmony_ci		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
15138c2ecf20Sopenharmony_ci			return;
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci		__stop_tx_rs485(p);
15168c2ecf20Sopenharmony_ci	}
15178c2ecf20Sopenharmony_ci	__do_stop_tx(p);
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic void serial8250_stop_tx(struct uart_port *port)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
15258c2ecf20Sopenharmony_ci	__stop_tx(up);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	/*
15288c2ecf20Sopenharmony_ci	 * We really want to stop the transmitter from sending.
15298c2ecf20Sopenharmony_ci	 */
15308c2ecf20Sopenharmony_ci	if (port->type == PORT_16C950) {
15318c2ecf20Sopenharmony_ci		up->acr |= UART_ACR_TXDIS;
15328c2ecf20Sopenharmony_ci		serial_icr_write(up, UART_ACR, up->acr);
15338c2ecf20Sopenharmony_ci	}
15348c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
15358c2ecf20Sopenharmony_ci}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_cistatic inline void __start_tx(struct uart_port *port)
15388c2ecf20Sopenharmony_ci{
15398c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci	if (up->dma && !up->dma->tx_dma(up))
15428c2ecf20Sopenharmony_ci		return;
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci	if (serial8250_set_THRI(up)) {
15458c2ecf20Sopenharmony_ci		if (up->bugs & UART_BUG_TXEN) {
15468c2ecf20Sopenharmony_ci			unsigned char lsr;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci			lsr = serial_in(up, UART_LSR);
15498c2ecf20Sopenharmony_ci			up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
15508c2ecf20Sopenharmony_ci			if (lsr & UART_LSR_THRE)
15518c2ecf20Sopenharmony_ci				serial8250_tx_chars(up);
15528c2ecf20Sopenharmony_ci		}
15538c2ecf20Sopenharmony_ci	}
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	/*
15568c2ecf20Sopenharmony_ci	 * Re-enable the transmitter if we disabled it.
15578c2ecf20Sopenharmony_ci	 */
15588c2ecf20Sopenharmony_ci	if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
15598c2ecf20Sopenharmony_ci		up->acr &= ~UART_ACR_TXDIS;
15608c2ecf20Sopenharmony_ci		serial_icr_write(up, UART_ACR, up->acr);
15618c2ecf20Sopenharmony_ci	}
15628c2ecf20Sopenharmony_ci}
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci/**
15658c2ecf20Sopenharmony_ci * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback
15668c2ecf20Sopenharmony_ci * @up: uart 8250 port
15678c2ecf20Sopenharmony_ci *
15688c2ecf20Sopenharmony_ci * Generic callback usable by 8250 uart drivers to start rs485 transmission.
15698c2ecf20Sopenharmony_ci * Assumes that setting the RTS bit in the MCR register means RTS is high.
15708c2ecf20Sopenharmony_ci * (Some chips use inverse semantics.)  Further assumes that reception is
15718c2ecf20Sopenharmony_ci * stoppable by disabling the UART_IER_RDI interrupt.  (Some chips set the
15728c2ecf20Sopenharmony_ci * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.)
15738c2ecf20Sopenharmony_ci */
15748c2ecf20Sopenharmony_civoid serial8250_em485_start_tx(struct uart_8250_port *up)
15758c2ecf20Sopenharmony_ci{
15768c2ecf20Sopenharmony_ci	unsigned char mcr = serial8250_in_MCR(up);
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
15798c2ecf20Sopenharmony_ci		serial8250_stop_rx(&up->port);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
15828c2ecf20Sopenharmony_ci		mcr |= UART_MCR_RTS;
15838c2ecf20Sopenharmony_ci	else
15848c2ecf20Sopenharmony_ci		mcr &= ~UART_MCR_RTS;
15858c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, mcr);
15868c2ecf20Sopenharmony_ci}
15878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_em485_start_tx);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_cistatic inline void start_tx_rs485(struct uart_port *port)
15908c2ecf20Sopenharmony_ci{
15918c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
15928c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485 = up->em485;
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	/*
15958c2ecf20Sopenharmony_ci	 * While serial8250_em485_handle_stop_tx() is a noop if
15968c2ecf20Sopenharmony_ci	 * em485->active_timer != &em485->stop_tx_timer, it might happen that
15978c2ecf20Sopenharmony_ci	 * the timer is still armed and triggers only after the current bunch of
15988c2ecf20Sopenharmony_ci	 * chars is send and em485->active_timer == &em485->stop_tx_timer again.
15998c2ecf20Sopenharmony_ci	 * So cancel the timer. There is still a theoretical race condition if
16008c2ecf20Sopenharmony_ci	 * the timer is already running and only comes around to check for
16018c2ecf20Sopenharmony_ci	 * em485->active_timer when &em485->stop_tx_timer is armed again.
16028c2ecf20Sopenharmony_ci	 */
16038c2ecf20Sopenharmony_ci	if (em485->active_timer == &em485->stop_tx_timer)
16048c2ecf20Sopenharmony_ci		hrtimer_try_to_cancel(&em485->stop_tx_timer);
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	em485->active_timer = NULL;
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	if (em485->tx_stopped) {
16098c2ecf20Sopenharmony_ci		em485->tx_stopped = false;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci		up->rs485_start_tx(up);
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ci		if (up->port.rs485.delay_rts_before_send > 0) {
16148c2ecf20Sopenharmony_ci			em485->active_timer = &em485->start_tx_timer;
16158c2ecf20Sopenharmony_ci			start_hrtimer_ms(&em485->start_tx_timer,
16168c2ecf20Sopenharmony_ci					 up->port.rs485.delay_rts_before_send);
16178c2ecf20Sopenharmony_ci			return;
16188c2ecf20Sopenharmony_ci		}
16198c2ecf20Sopenharmony_ci	}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	__start_tx(port);
16228c2ecf20Sopenharmony_ci}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_cistatic enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
16258c2ecf20Sopenharmony_ci{
16268c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485;
16278c2ecf20Sopenharmony_ci	struct uart_8250_port *p;
16288c2ecf20Sopenharmony_ci	unsigned long flags;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	em485 = container_of(t, struct uart_8250_em485, start_tx_timer);
16318c2ecf20Sopenharmony_ci	p = em485->port;
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	spin_lock_irqsave(&p->port.lock, flags);
16348c2ecf20Sopenharmony_ci	if (em485->active_timer == &em485->start_tx_timer) {
16358c2ecf20Sopenharmony_ci		__start_tx(&p->port);
16368c2ecf20Sopenharmony_ci		em485->active_timer = NULL;
16378c2ecf20Sopenharmony_ci	}
16388c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&p->port.lock, flags);
16398c2ecf20Sopenharmony_ci	return HRTIMER_NORESTART;
16408c2ecf20Sopenharmony_ci}
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_cistatic void serial8250_start_tx(struct uart_port *port)
16438c2ecf20Sopenharmony_ci{
16448c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
16458c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485 = up->em485;
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	serial8250_rpm_get_tx(up);
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	if (em485 &&
16508c2ecf20Sopenharmony_ci	    em485->active_timer == &em485->start_tx_timer)
16518c2ecf20Sopenharmony_ci		return;
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	if (em485)
16548c2ecf20Sopenharmony_ci		start_tx_rs485(port);
16558c2ecf20Sopenharmony_ci	else
16568c2ecf20Sopenharmony_ci		__start_tx(port);
16578c2ecf20Sopenharmony_ci}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_cistatic void serial8250_throttle(struct uart_port *port)
16608c2ecf20Sopenharmony_ci{
16618c2ecf20Sopenharmony_ci	port->throttle(port);
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_cistatic void serial8250_unthrottle(struct uart_port *port)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	port->unthrottle(port);
16678c2ecf20Sopenharmony_ci}
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_cistatic void serial8250_disable_ms(struct uart_port *port)
16708c2ecf20Sopenharmony_ci{
16718c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
16728c2ecf20Sopenharmony_ci
16738c2ecf20Sopenharmony_ci	/* no MSR capabilities */
16748c2ecf20Sopenharmony_ci	if (up->bugs & UART_BUG_NOMSR)
16758c2ecf20Sopenharmony_ci		return;
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	mctrl_gpio_disable_ms(up->gpios);
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	up->ier &= ~UART_IER_MSI;
16808c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, up->ier);
16818c2ecf20Sopenharmony_ci}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_cistatic void serial8250_enable_ms(struct uart_port *port)
16848c2ecf20Sopenharmony_ci{
16858c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	/* no MSR capabilities */
16888c2ecf20Sopenharmony_ci	if (up->bugs & UART_BUG_NOMSR)
16898c2ecf20Sopenharmony_ci		return;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	mctrl_gpio_enable_ms(up->gpios);
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	up->ier |= UART_IER_MSI;
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
16968c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, up->ier);
16978c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
16988c2ecf20Sopenharmony_ci}
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_civoid serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
17018c2ecf20Sopenharmony_ci{
17028c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
17038c2ecf20Sopenharmony_ci	unsigned char ch;
17048c2ecf20Sopenharmony_ci	char flag = TTY_NORMAL;
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	if (likely(lsr & UART_LSR_DR))
17078c2ecf20Sopenharmony_ci		ch = serial_in(up, UART_RX);
17088c2ecf20Sopenharmony_ci	else
17098c2ecf20Sopenharmony_ci		/*
17108c2ecf20Sopenharmony_ci		 * Intel 82571 has a Serial Over Lan device that will
17118c2ecf20Sopenharmony_ci		 * set UART_LSR_BI without setting UART_LSR_DR when
17128c2ecf20Sopenharmony_ci		 * it receives a break. To avoid reading from the
17138c2ecf20Sopenharmony_ci		 * receive buffer without UART_LSR_DR bit set, we
17148c2ecf20Sopenharmony_ci		 * just force the read character to be 0
17158c2ecf20Sopenharmony_ci		 */
17168c2ecf20Sopenharmony_ci		ch = 0;
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	port->icount.rx++;
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci	lsr |= up->lsr_saved_flags;
17218c2ecf20Sopenharmony_ci	up->lsr_saved_flags = 0;
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
17248c2ecf20Sopenharmony_ci		if (lsr & UART_LSR_BI) {
17258c2ecf20Sopenharmony_ci			lsr &= ~(UART_LSR_FE | UART_LSR_PE);
17268c2ecf20Sopenharmony_ci			port->icount.brk++;
17278c2ecf20Sopenharmony_ci			/*
17288c2ecf20Sopenharmony_ci			 * We do the SysRQ and SAK checking
17298c2ecf20Sopenharmony_ci			 * here because otherwise the break
17308c2ecf20Sopenharmony_ci			 * may get masked by ignore_status_mask
17318c2ecf20Sopenharmony_ci			 * or read_status_mask.
17328c2ecf20Sopenharmony_ci			 */
17338c2ecf20Sopenharmony_ci			if (uart_handle_break(port))
17348c2ecf20Sopenharmony_ci				return;
17358c2ecf20Sopenharmony_ci		} else if (lsr & UART_LSR_PE)
17368c2ecf20Sopenharmony_ci			port->icount.parity++;
17378c2ecf20Sopenharmony_ci		else if (lsr & UART_LSR_FE)
17388c2ecf20Sopenharmony_ci			port->icount.frame++;
17398c2ecf20Sopenharmony_ci		if (lsr & UART_LSR_OE)
17408c2ecf20Sopenharmony_ci			port->icount.overrun++;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci		/*
17438c2ecf20Sopenharmony_ci		 * Mask off conditions which should be ignored.
17448c2ecf20Sopenharmony_ci		 */
17458c2ecf20Sopenharmony_ci		lsr &= port->read_status_mask;
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci		if (lsr & UART_LSR_BI) {
17488c2ecf20Sopenharmony_ci			dev_dbg(port->dev, "handling break\n");
17498c2ecf20Sopenharmony_ci			flag = TTY_BREAK;
17508c2ecf20Sopenharmony_ci		} else if (lsr & UART_LSR_PE)
17518c2ecf20Sopenharmony_ci			flag = TTY_PARITY;
17528c2ecf20Sopenharmony_ci		else if (lsr & UART_LSR_FE)
17538c2ecf20Sopenharmony_ci			flag = TTY_FRAME;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ci	if (uart_prepare_sysrq_char(port, ch))
17568c2ecf20Sopenharmony_ci		return;
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
17598c2ecf20Sopenharmony_ci}
17608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_read_char);
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci/*
17638c2ecf20Sopenharmony_ci * serial8250_rx_chars: processes according to the passed in LSR
17648c2ecf20Sopenharmony_ci * value, and returns the remaining LSR bits not handled
17658c2ecf20Sopenharmony_ci * by this Rx routine.
17668c2ecf20Sopenharmony_ci */
17678c2ecf20Sopenharmony_ciunsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
17688c2ecf20Sopenharmony_ci{
17698c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
17708c2ecf20Sopenharmony_ci	int max_count = 256;
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	do {
17738c2ecf20Sopenharmony_ci		serial8250_read_char(up, lsr);
17748c2ecf20Sopenharmony_ci		if (--max_count == 0)
17758c2ecf20Sopenharmony_ci			break;
17768c2ecf20Sopenharmony_ci		lsr = serial_in(up, UART_LSR);
17778c2ecf20Sopenharmony_ci	} while (lsr & (UART_LSR_DR | UART_LSR_BI));
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	tty_flip_buffer_push(&port->state->port);
17808c2ecf20Sopenharmony_ci	return lsr;
17818c2ecf20Sopenharmony_ci}
17828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_rx_chars);
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_civoid serial8250_tx_chars(struct uart_8250_port *up)
17858c2ecf20Sopenharmony_ci{
17868c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
17878c2ecf20Sopenharmony_ci	struct circ_buf *xmit = &port->state->xmit;
17888c2ecf20Sopenharmony_ci	int count;
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	if (port->x_char) {
17918c2ecf20Sopenharmony_ci		uart_xchar_out(port, UART_TX);
17928c2ecf20Sopenharmony_ci		return;
17938c2ecf20Sopenharmony_ci	}
17948c2ecf20Sopenharmony_ci	if (uart_tx_stopped(port)) {
17958c2ecf20Sopenharmony_ci		serial8250_stop_tx(port);
17968c2ecf20Sopenharmony_ci		return;
17978c2ecf20Sopenharmony_ci	}
17988c2ecf20Sopenharmony_ci	if (uart_circ_empty(xmit)) {
17998c2ecf20Sopenharmony_ci		__stop_tx(up);
18008c2ecf20Sopenharmony_ci		return;
18018c2ecf20Sopenharmony_ci	}
18028c2ecf20Sopenharmony_ci
18038c2ecf20Sopenharmony_ci	count = up->tx_loadsz;
18048c2ecf20Sopenharmony_ci	do {
18058c2ecf20Sopenharmony_ci		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
18068c2ecf20Sopenharmony_ci		if (up->bugs & UART_BUG_TXRACE) {
18078c2ecf20Sopenharmony_ci			/*
18088c2ecf20Sopenharmony_ci			 * The Aspeed BMC virtual UARTs have a bug where data
18098c2ecf20Sopenharmony_ci			 * may get stuck in the BMC's Tx FIFO from bursts of
18108c2ecf20Sopenharmony_ci			 * writes on the APB interface.
18118c2ecf20Sopenharmony_ci			 *
18128c2ecf20Sopenharmony_ci			 * Delay back-to-back writes by a read cycle to avoid
18138c2ecf20Sopenharmony_ci			 * stalling the VUART. Read a register that won't have
18148c2ecf20Sopenharmony_ci			 * side-effects and discard the result.
18158c2ecf20Sopenharmony_ci			 */
18168c2ecf20Sopenharmony_ci			serial_in(up, UART_SCR);
18178c2ecf20Sopenharmony_ci		}
18188c2ecf20Sopenharmony_ci		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
18198c2ecf20Sopenharmony_ci		port->icount.tx++;
18208c2ecf20Sopenharmony_ci		if (uart_circ_empty(xmit))
18218c2ecf20Sopenharmony_ci			break;
18228c2ecf20Sopenharmony_ci		if ((up->capabilities & UART_CAP_HFIFO) &&
18238c2ecf20Sopenharmony_ci		    (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY)
18248c2ecf20Sopenharmony_ci			break;
18258c2ecf20Sopenharmony_ci		/* The BCM2835 MINI UART THRE bit is really a not-full bit. */
18268c2ecf20Sopenharmony_ci		if ((up->capabilities & UART_CAP_MINI) &&
18278c2ecf20Sopenharmony_ci		    !(serial_in(up, UART_LSR) & UART_LSR_THRE))
18288c2ecf20Sopenharmony_ci			break;
18298c2ecf20Sopenharmony_ci	} while (--count > 0);
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
18328c2ecf20Sopenharmony_ci		uart_write_wakeup(port);
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	/*
18358c2ecf20Sopenharmony_ci	 * With RPM enabled, we have to wait until the FIFO is empty before the
18368c2ecf20Sopenharmony_ci	 * HW can go idle. So we get here once again with empty FIFO and disable
18378c2ecf20Sopenharmony_ci	 * the interrupt and RPM in __stop_tx()
18388c2ecf20Sopenharmony_ci	 */
18398c2ecf20Sopenharmony_ci	if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
18408c2ecf20Sopenharmony_ci		__stop_tx(up);
18418c2ecf20Sopenharmony_ci}
18428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_tx_chars);
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci/* Caller holds uart port lock */
18458c2ecf20Sopenharmony_ciunsigned int serial8250_modem_status(struct uart_8250_port *up)
18468c2ecf20Sopenharmony_ci{
18478c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
18488c2ecf20Sopenharmony_ci	unsigned int status = serial_in(up, UART_MSR);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	status |= up->msr_saved_flags;
18518c2ecf20Sopenharmony_ci	up->msr_saved_flags = 0;
18528c2ecf20Sopenharmony_ci	if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
18538c2ecf20Sopenharmony_ci	    port->state != NULL) {
18548c2ecf20Sopenharmony_ci		if (status & UART_MSR_TERI)
18558c2ecf20Sopenharmony_ci			port->icount.rng++;
18568c2ecf20Sopenharmony_ci		if (status & UART_MSR_DDSR)
18578c2ecf20Sopenharmony_ci			port->icount.dsr++;
18588c2ecf20Sopenharmony_ci		if (status & UART_MSR_DDCD)
18598c2ecf20Sopenharmony_ci			uart_handle_dcd_change(port, status & UART_MSR_DCD);
18608c2ecf20Sopenharmony_ci		if (status & UART_MSR_DCTS)
18618c2ecf20Sopenharmony_ci			uart_handle_cts_change(port, status & UART_MSR_CTS);
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci		wake_up_interruptible(&port->state->port.delta_msr_wait);
18648c2ecf20Sopenharmony_ci	}
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	return status;
18678c2ecf20Sopenharmony_ci}
18688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_modem_status);
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_cistatic bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
18718c2ecf20Sopenharmony_ci{
18728c2ecf20Sopenharmony_ci	switch (iir & 0x3f) {
18738c2ecf20Sopenharmony_ci	case UART_IIR_RDI:
18748c2ecf20Sopenharmony_ci		if (!up->dma->rx_running)
18758c2ecf20Sopenharmony_ci			break;
18768c2ecf20Sopenharmony_ci		fallthrough;
18778c2ecf20Sopenharmony_ci	case UART_IIR_RLSI:
18788c2ecf20Sopenharmony_ci	case UART_IIR_RX_TIMEOUT:
18798c2ecf20Sopenharmony_ci		serial8250_rx_dma_flush(up);
18808c2ecf20Sopenharmony_ci		return true;
18818c2ecf20Sopenharmony_ci	}
18828c2ecf20Sopenharmony_ci	return up->dma->rx_dma(up);
18838c2ecf20Sopenharmony_ci}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci/*
18868c2ecf20Sopenharmony_ci * This handles the interrupt from one port.
18878c2ecf20Sopenharmony_ci */
18888c2ecf20Sopenharmony_ciint serial8250_handle_irq(struct uart_port *port, unsigned int iir)
18898c2ecf20Sopenharmony_ci{
18908c2ecf20Sopenharmony_ci	unsigned char status;
18918c2ecf20Sopenharmony_ci	unsigned long flags;
18928c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
18938c2ecf20Sopenharmony_ci	struct tty_port *tport = &port->state->port;
18948c2ecf20Sopenharmony_ci	bool skip_rx = false;
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci	if (iir & UART_IIR_NO_INT)
18978c2ecf20Sopenharmony_ci		return 0;
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	status = serial_port_in(port, UART_LSR);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	/*
19048c2ecf20Sopenharmony_ci	 * If port is stopped and there are no error conditions in the
19058c2ecf20Sopenharmony_ci	 * FIFO, then don't drain the FIFO, as this may lead to TTY buffer
19068c2ecf20Sopenharmony_ci	 * overflow. Not servicing, RX FIFO would trigger auto HW flow
19078c2ecf20Sopenharmony_ci	 * control when FIFO occupancy reaches preset threshold, thus
19088c2ecf20Sopenharmony_ci	 * halting RX. This only works when auto HW flow control is
19098c2ecf20Sopenharmony_ci	 * available.
19108c2ecf20Sopenharmony_ci	 */
19118c2ecf20Sopenharmony_ci	if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) &&
19128c2ecf20Sopenharmony_ci	    (port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) &&
19138c2ecf20Sopenharmony_ci	    !(port->read_status_mask & UART_LSR_DR))
19148c2ecf20Sopenharmony_ci		skip_rx = true;
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci	if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
19178c2ecf20Sopenharmony_ci		struct irq_data *d;
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci		d = irq_get_irq_data(port->irq);
19208c2ecf20Sopenharmony_ci		if (d && irqd_is_wakeup_set(d))
19218c2ecf20Sopenharmony_ci			pm_wakeup_event(tport->tty->dev, 0);
19228c2ecf20Sopenharmony_ci		if (!up->dma || handle_rx_dma(up, iir))
19238c2ecf20Sopenharmony_ci			status = serial8250_rx_chars(up, status);
19248c2ecf20Sopenharmony_ci	}
19258c2ecf20Sopenharmony_ci	serial8250_modem_status(up);
19268c2ecf20Sopenharmony_ci	if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
19278c2ecf20Sopenharmony_ci		(up->ier & UART_IER_THRI))
19288c2ecf20Sopenharmony_ci		serial8250_tx_chars(up);
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	uart_unlock_and_check_sysrq(port, flags);
19318c2ecf20Sopenharmony_ci	return 1;
19328c2ecf20Sopenharmony_ci}
19338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_handle_irq);
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_cistatic int serial8250_default_handle_irq(struct uart_port *port)
19368c2ecf20Sopenharmony_ci{
19378c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
19388c2ecf20Sopenharmony_ci	unsigned int iir;
19398c2ecf20Sopenharmony_ci	int ret;
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	iir = serial_port_in(port, UART_IIR);
19448c2ecf20Sopenharmony_ci	ret = serial8250_handle_irq(port, iir);
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
19478c2ecf20Sopenharmony_ci	return ret;
19488c2ecf20Sopenharmony_ci}
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci/*
19518c2ecf20Sopenharmony_ci * Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP
19528c2ecf20Sopenharmony_ci * have a programmable TX threshold that triggers the THRE interrupt in
19538c2ecf20Sopenharmony_ci * the IIR register. In this case, the THRE interrupt indicates the FIFO
19548c2ecf20Sopenharmony_ci * has space available. Load it up with tx_loadsz bytes.
19558c2ecf20Sopenharmony_ci */
19568c2ecf20Sopenharmony_cistatic int serial8250_tx_threshold_handle_irq(struct uart_port *port)
19578c2ecf20Sopenharmony_ci{
19588c2ecf20Sopenharmony_ci	unsigned long flags;
19598c2ecf20Sopenharmony_ci	unsigned int iir = serial_port_in(port, UART_IIR);
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	/* TX Threshold IRQ triggered so load up FIFO */
19628c2ecf20Sopenharmony_ci	if ((iir & UART_IIR_ID) == UART_IIR_THRI) {
19638c2ecf20Sopenharmony_ci		struct uart_8250_port *up = up_to_u8250p(port);
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci		spin_lock_irqsave(&port->lock, flags);
19668c2ecf20Sopenharmony_ci		serial8250_tx_chars(up);
19678c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&port->lock, flags);
19688c2ecf20Sopenharmony_ci	}
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	iir = serial_port_in(port, UART_IIR);
19718c2ecf20Sopenharmony_ci	return serial8250_handle_irq(port, iir);
19728c2ecf20Sopenharmony_ci}
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_cistatic unsigned int serial8250_tx_empty(struct uart_port *port)
19758c2ecf20Sopenharmony_ci{
19768c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
19778c2ecf20Sopenharmony_ci	unsigned int result = 0;
19788c2ecf20Sopenharmony_ci	unsigned long flags;
19798c2ecf20Sopenharmony_ci	unsigned int lsr;
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
19848c2ecf20Sopenharmony_ci	if (!serial8250_tx_dma_running(up)) {
19858c2ecf20Sopenharmony_ci		lsr = serial_port_in(port, UART_LSR);
19868c2ecf20Sopenharmony_ci		up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci		if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
19898c2ecf20Sopenharmony_ci			result = TIOCSER_TEMT;
19908c2ecf20Sopenharmony_ci	}
19918c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	return result;
19968c2ecf20Sopenharmony_ci}
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ciunsigned int serial8250_do_get_mctrl(struct uart_port *port)
19998c2ecf20Sopenharmony_ci{
20008c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
20018c2ecf20Sopenharmony_ci	unsigned int status;
20028c2ecf20Sopenharmony_ci	unsigned int val;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
20058c2ecf20Sopenharmony_ci	status = serial8250_modem_status(up);
20068c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	val = serial8250_MSR_to_TIOCM(status);
20098c2ecf20Sopenharmony_ci	if (up->gpios)
20108c2ecf20Sopenharmony_ci		return mctrl_gpio_get(up->gpios, &val);
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	return val;
20138c2ecf20Sopenharmony_ci}
20148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_get_mctrl);
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_cistatic unsigned int serial8250_get_mctrl(struct uart_port *port)
20178c2ecf20Sopenharmony_ci{
20188c2ecf20Sopenharmony_ci	if (port->get_mctrl)
20198c2ecf20Sopenharmony_ci		return port->get_mctrl(port);
20208c2ecf20Sopenharmony_ci	return serial8250_do_get_mctrl(port);
20218c2ecf20Sopenharmony_ci}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_civoid serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
20248c2ecf20Sopenharmony_ci{
20258c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
20268c2ecf20Sopenharmony_ci	unsigned char mcr;
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	mcr = serial8250_TIOCM_to_MCR(mctrl);
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, mcr);
20338c2ecf20Sopenharmony_ci}
20348c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_cistatic void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
20378c2ecf20Sopenharmony_ci{
20388c2ecf20Sopenharmony_ci	if (port->rs485.flags & SER_RS485_ENABLED)
20398c2ecf20Sopenharmony_ci		return;
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci	if (port->set_mctrl)
20428c2ecf20Sopenharmony_ci		port->set_mctrl(port, mctrl);
20438c2ecf20Sopenharmony_ci	else
20448c2ecf20Sopenharmony_ci		serial8250_do_set_mctrl(port, mctrl);
20458c2ecf20Sopenharmony_ci}
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_cistatic void serial8250_break_ctl(struct uart_port *port, int break_state)
20488c2ecf20Sopenharmony_ci{
20498c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
20508c2ecf20Sopenharmony_ci	unsigned long flags;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
20538c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
20548c2ecf20Sopenharmony_ci	if (break_state == -1)
20558c2ecf20Sopenharmony_ci		up->lcr |= UART_LCR_SBC;
20568c2ecf20Sopenharmony_ci	else
20578c2ecf20Sopenharmony_ci		up->lcr &= ~UART_LCR_SBC;
20588c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, up->lcr);
20598c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
20608c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
20618c2ecf20Sopenharmony_ci}
20628c2ecf20Sopenharmony_ci
20638c2ecf20Sopenharmony_ci/*
20648c2ecf20Sopenharmony_ci *	Wait for transmitter & holding register to empty
20658c2ecf20Sopenharmony_ci */
20668c2ecf20Sopenharmony_cistatic void wait_for_xmitr(struct uart_8250_port *up, int bits)
20678c2ecf20Sopenharmony_ci{
20688c2ecf20Sopenharmony_ci	unsigned int status, tmout = 10000;
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	/* Wait up to 10ms for the character(s) to be sent. */
20718c2ecf20Sopenharmony_ci	for (;;) {
20728c2ecf20Sopenharmony_ci		status = serial_in(up, UART_LSR);
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci		up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci		if ((status & bits) == bits)
20778c2ecf20Sopenharmony_ci			break;
20788c2ecf20Sopenharmony_ci		if (--tmout == 0)
20798c2ecf20Sopenharmony_ci			break;
20808c2ecf20Sopenharmony_ci		udelay(1);
20818c2ecf20Sopenharmony_ci		touch_nmi_watchdog();
20828c2ecf20Sopenharmony_ci	}
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	/* Wait up to 1s for flow control if necessary */
20858c2ecf20Sopenharmony_ci	if (up->port.flags & UPF_CONS_FLOW) {
20868c2ecf20Sopenharmony_ci		for (tmout = 1000000; tmout; tmout--) {
20878c2ecf20Sopenharmony_ci			unsigned int msr = serial_in(up, UART_MSR);
20888c2ecf20Sopenharmony_ci			up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
20898c2ecf20Sopenharmony_ci			if (msr & UART_MSR_CTS)
20908c2ecf20Sopenharmony_ci				break;
20918c2ecf20Sopenharmony_ci			udelay(1);
20928c2ecf20Sopenharmony_ci			touch_nmi_watchdog();
20938c2ecf20Sopenharmony_ci		}
20948c2ecf20Sopenharmony_ci	}
20958c2ecf20Sopenharmony_ci}
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_ci#ifdef CONFIG_CONSOLE_POLL
20988c2ecf20Sopenharmony_ci/*
20998c2ecf20Sopenharmony_ci * Console polling routines for writing and reading from the uart while
21008c2ecf20Sopenharmony_ci * in an interrupt or debug context.
21018c2ecf20Sopenharmony_ci */
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_cistatic int serial8250_get_poll_char(struct uart_port *port)
21048c2ecf20Sopenharmony_ci{
21058c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
21068c2ecf20Sopenharmony_ci	unsigned char lsr;
21078c2ecf20Sopenharmony_ci	int status;
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	lsr = serial_port_in(port, UART_LSR);
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	if (!(lsr & UART_LSR_DR)) {
21148c2ecf20Sopenharmony_ci		status = NO_POLL_CHAR;
21158c2ecf20Sopenharmony_ci		goto out;
21168c2ecf20Sopenharmony_ci	}
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_ci	status = serial_port_in(port, UART_RX);
21198c2ecf20Sopenharmony_ciout:
21208c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
21218c2ecf20Sopenharmony_ci	return status;
21228c2ecf20Sopenharmony_ci}
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_cistatic void serial8250_put_poll_char(struct uart_port *port,
21268c2ecf20Sopenharmony_ci			 unsigned char c)
21278c2ecf20Sopenharmony_ci{
21288c2ecf20Sopenharmony_ci	unsigned int ier;
21298c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
21328c2ecf20Sopenharmony_ci	/*
21338c2ecf20Sopenharmony_ci	 *	First save the IER then disable the interrupts
21348c2ecf20Sopenharmony_ci	 */
21358c2ecf20Sopenharmony_ci	ier = serial_port_in(port, UART_IER);
21368c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_UUE)
21378c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, UART_IER_UUE);
21388c2ecf20Sopenharmony_ci	else
21398c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci	wait_for_xmitr(up, BOTH_EMPTY);
21428c2ecf20Sopenharmony_ci	/*
21438c2ecf20Sopenharmony_ci	 *	Send the character out.
21448c2ecf20Sopenharmony_ci	 */
21458c2ecf20Sopenharmony_ci	serial_port_out(port, UART_TX, c);
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci	/*
21488c2ecf20Sopenharmony_ci	 *	Finally, wait for transmitter to become empty
21498c2ecf20Sopenharmony_ci	 *	and restore the IER
21508c2ecf20Sopenharmony_ci	 */
21518c2ecf20Sopenharmony_ci	wait_for_xmitr(up, BOTH_EMPTY);
21528c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, ier);
21538c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
21548c2ecf20Sopenharmony_ci}
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci#endif /* CONFIG_CONSOLE_POLL */
21578c2ecf20Sopenharmony_ci
21588c2ecf20Sopenharmony_ciint serial8250_do_startup(struct uart_port *port)
21598c2ecf20Sopenharmony_ci{
21608c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
21618c2ecf20Sopenharmony_ci	unsigned long flags;
21628c2ecf20Sopenharmony_ci	unsigned char lsr, iir;
21638c2ecf20Sopenharmony_ci	int retval;
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	if (!port->fifosize)
21668c2ecf20Sopenharmony_ci		port->fifosize = uart_config[port->type].fifo_size;
21678c2ecf20Sopenharmony_ci	if (!up->tx_loadsz)
21688c2ecf20Sopenharmony_ci		up->tx_loadsz = uart_config[port->type].tx_loadsz;
21698c2ecf20Sopenharmony_ci	if (!up->capabilities)
21708c2ecf20Sopenharmony_ci		up->capabilities = uart_config[port->type].flags;
21718c2ecf20Sopenharmony_ci	up->mcr = 0;
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci	if (port->iotype != up->cur_iotype)
21748c2ecf20Sopenharmony_ci		set_io_from_upio(port);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
21778c2ecf20Sopenharmony_ci	if (port->type == PORT_16C950) {
21788c2ecf20Sopenharmony_ci		/* Wake up and initialize UART */
21798c2ecf20Sopenharmony_ci		up->acr = 0;
21808c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
21818c2ecf20Sopenharmony_ci		serial_port_out(port, UART_EFR, UART_EFR_ECB);
21828c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
21838c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, 0);
21848c2ecf20Sopenharmony_ci		serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
21858c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
21868c2ecf20Sopenharmony_ci		serial_port_out(port, UART_EFR, UART_EFR_ECB);
21878c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, 0);
21888c2ecf20Sopenharmony_ci	}
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	if (port->type == PORT_DA830) {
21918c2ecf20Sopenharmony_ci		/* Reset the port */
21928c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
21938c2ecf20Sopenharmony_ci		serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
21948c2ecf20Sopenharmony_ci		mdelay(10);
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci		/* Enable Tx, Rx and free run mode */
21978c2ecf20Sopenharmony_ci		serial_port_out(port, UART_DA830_PWREMU_MGMT,
21988c2ecf20Sopenharmony_ci				UART_DA830_PWREMU_MGMT_UTRST |
21998c2ecf20Sopenharmony_ci				UART_DA830_PWREMU_MGMT_URRST |
22008c2ecf20Sopenharmony_ci				UART_DA830_PWREMU_MGMT_FREE);
22018c2ecf20Sopenharmony_ci	}
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	if (port->type == PORT_NPCM) {
22048c2ecf20Sopenharmony_ci		/*
22058c2ecf20Sopenharmony_ci		 * Nuvoton calls the scratch register 'UART_TOR' (timeout
22068c2ecf20Sopenharmony_ci		 * register). Enable it, and set TIOC (timeout interrupt
22078c2ecf20Sopenharmony_ci		 * comparator) to be 0x20 for correct operation.
22088c2ecf20Sopenharmony_ci		 */
22098c2ecf20Sopenharmony_ci		serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
22108c2ecf20Sopenharmony_ci	}
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RSA
22138c2ecf20Sopenharmony_ci	/*
22148c2ecf20Sopenharmony_ci	 * If this is an RSA port, see if we can kick it up to the
22158c2ecf20Sopenharmony_ci	 * higher speed clock.
22168c2ecf20Sopenharmony_ci	 */
22178c2ecf20Sopenharmony_ci	enable_rsa(up);
22188c2ecf20Sopenharmony_ci#endif
22198c2ecf20Sopenharmony_ci
22208c2ecf20Sopenharmony_ci	/*
22218c2ecf20Sopenharmony_ci	 * Clear the FIFO buffers and disable them.
22228c2ecf20Sopenharmony_ci	 * (they will be reenabled in set_termios())
22238c2ecf20Sopenharmony_ci	 */
22248c2ecf20Sopenharmony_ci	serial8250_clear_fifos(up);
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci	/*
22278c2ecf20Sopenharmony_ci	 * Clear the interrupt registers.
22288c2ecf20Sopenharmony_ci	 */
22298c2ecf20Sopenharmony_ci	serial_port_in(port, UART_LSR);
22308c2ecf20Sopenharmony_ci	serial_port_in(port, UART_RX);
22318c2ecf20Sopenharmony_ci	serial_port_in(port, UART_IIR);
22328c2ecf20Sopenharmony_ci	serial_port_in(port, UART_MSR);
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci	/*
22358c2ecf20Sopenharmony_ci	 * At this point, there's no way the LSR could still be 0xff;
22368c2ecf20Sopenharmony_ci	 * if it is, then bail out, because there's likely no UART
22378c2ecf20Sopenharmony_ci	 * here.
22388c2ecf20Sopenharmony_ci	 */
22398c2ecf20Sopenharmony_ci	if (!(port->flags & UPF_BUGGY_UART) &&
22408c2ecf20Sopenharmony_ci	    (serial_port_in(port, UART_LSR) == 0xff)) {
22418c2ecf20Sopenharmony_ci		dev_info_ratelimited(port->dev, "LSR safety check engaged!\n");
22428c2ecf20Sopenharmony_ci		retval = -ENODEV;
22438c2ecf20Sopenharmony_ci		goto out;
22448c2ecf20Sopenharmony_ci	}
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	/*
22478c2ecf20Sopenharmony_ci	 * For a XR16C850, we need to set the trigger levels
22488c2ecf20Sopenharmony_ci	 */
22498c2ecf20Sopenharmony_ci	if (port->type == PORT_16850) {
22508c2ecf20Sopenharmony_ci		unsigned char fctr;
22518c2ecf20Sopenharmony_ci
22528c2ecf20Sopenharmony_ci		serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_ci		fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
22558c2ecf20Sopenharmony_ci		serial_port_out(port, UART_FCTR,
22568c2ecf20Sopenharmony_ci				fctr | UART_FCTR_TRGD | UART_FCTR_RX);
22578c2ecf20Sopenharmony_ci		serial_port_out(port, UART_TRG, UART_TRG_96);
22588c2ecf20Sopenharmony_ci		serial_port_out(port, UART_FCTR,
22598c2ecf20Sopenharmony_ci				fctr | UART_FCTR_TRGD | UART_FCTR_TX);
22608c2ecf20Sopenharmony_ci		serial_port_out(port, UART_TRG, UART_TRG_96);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, 0);
22638c2ecf20Sopenharmony_ci	}
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci	/*
22668c2ecf20Sopenharmony_ci	 * For the Altera 16550 variants, set TX threshold trigger level.
22678c2ecf20Sopenharmony_ci	 */
22688c2ecf20Sopenharmony_ci	if (((port->type == PORT_ALTR_16550_F32) ||
22698c2ecf20Sopenharmony_ci	     (port->type == PORT_ALTR_16550_F64) ||
22708c2ecf20Sopenharmony_ci	     (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) {
22718c2ecf20Sopenharmony_ci		/* Bounds checking of TX threshold (valid 0 to fifosize-2) */
22728c2ecf20Sopenharmony_ci		if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) {
22738c2ecf20Sopenharmony_ci			dev_err(port->dev, "TX FIFO Threshold errors, skipping\n");
22748c2ecf20Sopenharmony_ci		} else {
22758c2ecf20Sopenharmony_ci			serial_port_out(port, UART_ALTR_AFR,
22768c2ecf20Sopenharmony_ci					UART_ALTR_EN_TXFIFO_LW);
22778c2ecf20Sopenharmony_ci			serial_port_out(port, UART_ALTR_TX_LOW,
22788c2ecf20Sopenharmony_ci					port->fifosize - up->tx_loadsz);
22798c2ecf20Sopenharmony_ci			port->handle_irq = serial8250_tx_threshold_handle_irq;
22808c2ecf20Sopenharmony_ci		}
22818c2ecf20Sopenharmony_ci	}
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci	/* Check if we need to have shared IRQs */
22848c2ecf20Sopenharmony_ci	if (port->irq && (up->port.flags & UPF_SHARE_IRQ))
22858c2ecf20Sopenharmony_ci		up->port.irqflags |= IRQF_SHARED;
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci	retval = up->ops->setup_irq(up);
22888c2ecf20Sopenharmony_ci	if (retval)
22898c2ecf20Sopenharmony_ci		goto out;
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_ci	if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
22928c2ecf20Sopenharmony_ci		unsigned char iir1;
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci		if (port->irqflags & IRQF_SHARED)
22958c2ecf20Sopenharmony_ci			disable_irq_nosync(port->irq);
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci		/*
22988c2ecf20Sopenharmony_ci		 * Test for UARTs that do not reassert THRE when the
22998c2ecf20Sopenharmony_ci		 * transmitter is idle and the interrupt has already
23008c2ecf20Sopenharmony_ci		 * been cleared.  Real 16550s should always reassert
23018c2ecf20Sopenharmony_ci		 * this interrupt whenever the transmitter is idle and
23028c2ecf20Sopenharmony_ci		 * the interrupt is enabled.  Delays are necessary to
23038c2ecf20Sopenharmony_ci		 * allow register changes to become visible.
23048c2ecf20Sopenharmony_ci		 */
23058c2ecf20Sopenharmony_ci		spin_lock_irqsave(&port->lock, flags);
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci		wait_for_xmitr(up, UART_LSR_THRE);
23088c2ecf20Sopenharmony_ci		serial_port_out_sync(port, UART_IER, UART_IER_THRI);
23098c2ecf20Sopenharmony_ci		udelay(1); /* allow THRE to set */
23108c2ecf20Sopenharmony_ci		iir1 = serial_port_in(port, UART_IIR);
23118c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
23128c2ecf20Sopenharmony_ci		serial_port_out_sync(port, UART_IER, UART_IER_THRI);
23138c2ecf20Sopenharmony_ci		udelay(1); /* allow a working UART time to re-assert THRE */
23148c2ecf20Sopenharmony_ci		iir = serial_port_in(port, UART_IIR);
23158c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&port->lock, flags);
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_ci		if (port->irqflags & IRQF_SHARED)
23208c2ecf20Sopenharmony_ci			enable_irq(port->irq);
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci		/*
23238c2ecf20Sopenharmony_ci		 * If the interrupt is not reasserted, or we otherwise
23248c2ecf20Sopenharmony_ci		 * don't trust the iir, setup a timer to kick the UART
23258c2ecf20Sopenharmony_ci		 * on a regular basis.
23268c2ecf20Sopenharmony_ci		 */
23278c2ecf20Sopenharmony_ci		if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
23288c2ecf20Sopenharmony_ci		    up->port.flags & UPF_BUG_THRE) {
23298c2ecf20Sopenharmony_ci			up->bugs |= UART_BUG_THRE;
23308c2ecf20Sopenharmony_ci		}
23318c2ecf20Sopenharmony_ci	}
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci	up->ops->setup_timer(up);
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci	/*
23368c2ecf20Sopenharmony_ci	 * Now, initialize the UART
23378c2ecf20Sopenharmony_ci	 */
23388c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
23418c2ecf20Sopenharmony_ci	if (up->port.flags & UPF_FOURPORT) {
23428c2ecf20Sopenharmony_ci		if (!up->port.irq)
23438c2ecf20Sopenharmony_ci			up->port.mctrl |= TIOCM_OUT1;
23448c2ecf20Sopenharmony_ci	} else
23458c2ecf20Sopenharmony_ci		/*
23468c2ecf20Sopenharmony_ci		 * Most PC uarts need OUT2 raised to enable interrupts.
23478c2ecf20Sopenharmony_ci		 */
23488c2ecf20Sopenharmony_ci		if (port->irq)
23498c2ecf20Sopenharmony_ci			up->port.mctrl |= TIOCM_OUT2;
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci	serial8250_set_mctrl(port, port->mctrl);
23528c2ecf20Sopenharmony_ci
23538c2ecf20Sopenharmony_ci	/*
23548c2ecf20Sopenharmony_ci	 * Serial over Lan (SoL) hack:
23558c2ecf20Sopenharmony_ci	 * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be
23568c2ecf20Sopenharmony_ci	 * used for Serial Over Lan.  Those chips take a longer time than a
23578c2ecf20Sopenharmony_ci	 * normal serial device to signalize that a transmission data was
23588c2ecf20Sopenharmony_ci	 * queued. Due to that, the above test generally fails. One solution
23598c2ecf20Sopenharmony_ci	 * would be to delay the reading of iir. However, this is not
23608c2ecf20Sopenharmony_ci	 * reliable, since the timeout is variable. So, let's just don't
23618c2ecf20Sopenharmony_ci	 * test if we receive TX irq.  This way, we'll never enable
23628c2ecf20Sopenharmony_ci	 * UART_BUG_TXEN.
23638c2ecf20Sopenharmony_ci	 */
23648c2ecf20Sopenharmony_ci	if (up->port.quirks & UPQ_NO_TXEN_TEST)
23658c2ecf20Sopenharmony_ci		goto dont_test_tx_en;
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci	/*
23688c2ecf20Sopenharmony_ci	 * Do a quick test to see if we receive an interrupt when we enable
23698c2ecf20Sopenharmony_ci	 * the TX irq.
23708c2ecf20Sopenharmony_ci	 */
23718c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, UART_IER_THRI);
23728c2ecf20Sopenharmony_ci	lsr = serial_port_in(port, UART_LSR);
23738c2ecf20Sopenharmony_ci	iir = serial_port_in(port, UART_IIR);
23748c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, 0);
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
23778c2ecf20Sopenharmony_ci		if (!(up->bugs & UART_BUG_TXEN)) {
23788c2ecf20Sopenharmony_ci			up->bugs |= UART_BUG_TXEN;
23798c2ecf20Sopenharmony_ci			dev_dbg(port->dev, "enabling bad tx status workarounds\n");
23808c2ecf20Sopenharmony_ci		}
23818c2ecf20Sopenharmony_ci	} else {
23828c2ecf20Sopenharmony_ci		up->bugs &= ~UART_BUG_TXEN;
23838c2ecf20Sopenharmony_ci	}
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_cidont_test_tx_en:
23868c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci	/*
23898c2ecf20Sopenharmony_ci	 * Clear the interrupt registers again for luck, and clear the
23908c2ecf20Sopenharmony_ci	 * saved flags to avoid getting false values from polling
23918c2ecf20Sopenharmony_ci	 * routines or the previous session.
23928c2ecf20Sopenharmony_ci	 */
23938c2ecf20Sopenharmony_ci	serial_port_in(port, UART_LSR);
23948c2ecf20Sopenharmony_ci	serial_port_in(port, UART_RX);
23958c2ecf20Sopenharmony_ci	serial_port_in(port, UART_IIR);
23968c2ecf20Sopenharmony_ci	serial_port_in(port, UART_MSR);
23978c2ecf20Sopenharmony_ci	up->lsr_saved_flags = 0;
23988c2ecf20Sopenharmony_ci	up->msr_saved_flags = 0;
23998c2ecf20Sopenharmony_ci
24008c2ecf20Sopenharmony_ci	/*
24018c2ecf20Sopenharmony_ci	 * Request DMA channels for both RX and TX.
24028c2ecf20Sopenharmony_ci	 */
24038c2ecf20Sopenharmony_ci	if (up->dma) {
24048c2ecf20Sopenharmony_ci		const char *msg = NULL;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci		if (uart_console(port))
24078c2ecf20Sopenharmony_ci			msg = "forbid DMA for kernel console";
24088c2ecf20Sopenharmony_ci		else if (serial8250_request_dma(up))
24098c2ecf20Sopenharmony_ci			msg = "failed to request DMA";
24108c2ecf20Sopenharmony_ci		if (msg) {
24118c2ecf20Sopenharmony_ci			dev_warn_ratelimited(port->dev, "%s\n", msg);
24128c2ecf20Sopenharmony_ci			up->dma = NULL;
24138c2ecf20Sopenharmony_ci		}
24148c2ecf20Sopenharmony_ci	}
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci	/*
24178c2ecf20Sopenharmony_ci	 * Set the IER shadow for rx interrupts but defer actual interrupt
24188c2ecf20Sopenharmony_ci	 * enable until after the FIFOs are enabled; otherwise, an already-
24198c2ecf20Sopenharmony_ci	 * active sender can swamp the interrupt handler with "too much work".
24208c2ecf20Sopenharmony_ci	 */
24218c2ecf20Sopenharmony_ci	up->ier = UART_IER_RLSI | UART_IER_RDI;
24228c2ecf20Sopenharmony_ci
24238c2ecf20Sopenharmony_ci	if (port->flags & UPF_FOURPORT) {
24248c2ecf20Sopenharmony_ci		unsigned int icp;
24258c2ecf20Sopenharmony_ci		/*
24268c2ecf20Sopenharmony_ci		 * Enable interrupts on the AST Fourport board
24278c2ecf20Sopenharmony_ci		 */
24288c2ecf20Sopenharmony_ci		icp = (port->iobase & 0xfe0) | 0x01f;
24298c2ecf20Sopenharmony_ci		outb_p(0x80, icp);
24308c2ecf20Sopenharmony_ci		inb_p(icp);
24318c2ecf20Sopenharmony_ci	}
24328c2ecf20Sopenharmony_ci	retval = 0;
24338c2ecf20Sopenharmony_ciout:
24348c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
24358c2ecf20Sopenharmony_ci	return retval;
24368c2ecf20Sopenharmony_ci}
24378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_startup);
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_cistatic int serial8250_startup(struct uart_port *port)
24408c2ecf20Sopenharmony_ci{
24418c2ecf20Sopenharmony_ci	if (port->startup)
24428c2ecf20Sopenharmony_ci		return port->startup(port);
24438c2ecf20Sopenharmony_ci	return serial8250_do_startup(port);
24448c2ecf20Sopenharmony_ci}
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_civoid serial8250_do_shutdown(struct uart_port *port)
24478c2ecf20Sopenharmony_ci{
24488c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
24498c2ecf20Sopenharmony_ci	unsigned long flags;
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
24528c2ecf20Sopenharmony_ci	/*
24538c2ecf20Sopenharmony_ci	 * Disable interrupts from this port
24548c2ecf20Sopenharmony_ci	 */
24558c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
24568c2ecf20Sopenharmony_ci	up->ier = 0;
24578c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, 0);
24588c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci	synchronize_irq(port->irq);
24618c2ecf20Sopenharmony_ci
24628c2ecf20Sopenharmony_ci	if (up->dma)
24638c2ecf20Sopenharmony_ci		serial8250_release_dma(up);
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
24668c2ecf20Sopenharmony_ci	if (port->flags & UPF_FOURPORT) {
24678c2ecf20Sopenharmony_ci		/* reset interrupts on the AST Fourport board */
24688c2ecf20Sopenharmony_ci		inb((port->iobase & 0xfe0) | 0x1f);
24698c2ecf20Sopenharmony_ci		port->mctrl |= TIOCM_OUT1;
24708c2ecf20Sopenharmony_ci	} else
24718c2ecf20Sopenharmony_ci		port->mctrl &= ~TIOCM_OUT2;
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	serial8250_set_mctrl(port, port->mctrl);
24748c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	/*
24778c2ecf20Sopenharmony_ci	 * Disable break condition and FIFOs
24788c2ecf20Sopenharmony_ci	 */
24798c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR,
24808c2ecf20Sopenharmony_ci			serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
24818c2ecf20Sopenharmony_ci	serial8250_clear_fifos(up);
24828c2ecf20Sopenharmony_ci
24838c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_RSA
24848c2ecf20Sopenharmony_ci	/*
24858c2ecf20Sopenharmony_ci	 * Reset the RSA board back to 115kbps compat mode.
24868c2ecf20Sopenharmony_ci	 */
24878c2ecf20Sopenharmony_ci	disable_rsa(up);
24888c2ecf20Sopenharmony_ci#endif
24898c2ecf20Sopenharmony_ci
24908c2ecf20Sopenharmony_ci	/*
24918c2ecf20Sopenharmony_ci	 * Read data port to reset things, and then unlink from
24928c2ecf20Sopenharmony_ci	 * the IRQ chain.
24938c2ecf20Sopenharmony_ci	 */
24948c2ecf20Sopenharmony_ci	serial_port_in(port, UART_RX);
24958c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_ci	up->ops->release_irq(up);
24988c2ecf20Sopenharmony_ci}
24998c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_shutdown);
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_cistatic void serial8250_shutdown(struct uart_port *port)
25028c2ecf20Sopenharmony_ci{
25038c2ecf20Sopenharmony_ci	if (port->shutdown)
25048c2ecf20Sopenharmony_ci		port->shutdown(port);
25058c2ecf20Sopenharmony_ci	else
25068c2ecf20Sopenharmony_ci		serial8250_do_shutdown(port);
25078c2ecf20Sopenharmony_ci}
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci/* Nuvoton NPCM UARTs have a custom divisor calculation */
25108c2ecf20Sopenharmony_cistatic unsigned int npcm_get_divisor(struct uart_8250_port *up,
25118c2ecf20Sopenharmony_ci		unsigned int baud)
25128c2ecf20Sopenharmony_ci{
25138c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
25168c2ecf20Sopenharmony_ci}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_cistatic unsigned int serial8250_do_get_divisor(struct uart_port *port,
25198c2ecf20Sopenharmony_ci					      unsigned int baud,
25208c2ecf20Sopenharmony_ci					      unsigned int *frac)
25218c2ecf20Sopenharmony_ci{
25228c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
25238c2ecf20Sopenharmony_ci	unsigned int quot;
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	/*
25268c2ecf20Sopenharmony_ci	 * Handle magic divisors for baud rates above baud_base on
25278c2ecf20Sopenharmony_ci	 * SMSC SuperIO chips.
25288c2ecf20Sopenharmony_ci	 *
25298c2ecf20Sopenharmony_ci	 */
25308c2ecf20Sopenharmony_ci	if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
25318c2ecf20Sopenharmony_ci	    baud == (port->uartclk/4))
25328c2ecf20Sopenharmony_ci		quot = 0x8001;
25338c2ecf20Sopenharmony_ci	else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
25348c2ecf20Sopenharmony_ci		 baud == (port->uartclk/8))
25358c2ecf20Sopenharmony_ci		quot = 0x8002;
25368c2ecf20Sopenharmony_ci	else if (up->port.type == PORT_NPCM)
25378c2ecf20Sopenharmony_ci		quot = npcm_get_divisor(up, baud);
25388c2ecf20Sopenharmony_ci	else
25398c2ecf20Sopenharmony_ci		quot = uart_get_divisor(port, baud);
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	/*
25428c2ecf20Sopenharmony_ci	 * Oxford Semi 952 rev B workaround
25438c2ecf20Sopenharmony_ci	 */
25448c2ecf20Sopenharmony_ci	if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
25458c2ecf20Sopenharmony_ci		quot++;
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci	return quot;
25488c2ecf20Sopenharmony_ci}
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_cistatic unsigned int serial8250_get_divisor(struct uart_port *port,
25518c2ecf20Sopenharmony_ci					   unsigned int baud,
25528c2ecf20Sopenharmony_ci					   unsigned int *frac)
25538c2ecf20Sopenharmony_ci{
25548c2ecf20Sopenharmony_ci	if (port->get_divisor)
25558c2ecf20Sopenharmony_ci		return port->get_divisor(port, baud, frac);
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	return serial8250_do_get_divisor(port, baud, frac);
25588c2ecf20Sopenharmony_ci}
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_cistatic unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
25618c2ecf20Sopenharmony_ci					    tcflag_t c_cflag)
25628c2ecf20Sopenharmony_ci{
25638c2ecf20Sopenharmony_ci	unsigned char cval;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	switch (c_cflag & CSIZE) {
25668c2ecf20Sopenharmony_ci	case CS5:
25678c2ecf20Sopenharmony_ci		cval = UART_LCR_WLEN5;
25688c2ecf20Sopenharmony_ci		break;
25698c2ecf20Sopenharmony_ci	case CS6:
25708c2ecf20Sopenharmony_ci		cval = UART_LCR_WLEN6;
25718c2ecf20Sopenharmony_ci		break;
25728c2ecf20Sopenharmony_ci	case CS7:
25738c2ecf20Sopenharmony_ci		cval = UART_LCR_WLEN7;
25748c2ecf20Sopenharmony_ci		break;
25758c2ecf20Sopenharmony_ci	default:
25768c2ecf20Sopenharmony_ci	case CS8:
25778c2ecf20Sopenharmony_ci		cval = UART_LCR_WLEN8;
25788c2ecf20Sopenharmony_ci		break;
25798c2ecf20Sopenharmony_ci	}
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci	if (c_cflag & CSTOPB)
25828c2ecf20Sopenharmony_ci		cval |= UART_LCR_STOP;
25838c2ecf20Sopenharmony_ci	if (c_cflag & PARENB)
25848c2ecf20Sopenharmony_ci		cval |= UART_LCR_PARITY;
25858c2ecf20Sopenharmony_ci	if (!(c_cflag & PARODD))
25868c2ecf20Sopenharmony_ci		cval |= UART_LCR_EPAR;
25878c2ecf20Sopenharmony_ci#ifdef CMSPAR
25888c2ecf20Sopenharmony_ci	if (c_cflag & CMSPAR)
25898c2ecf20Sopenharmony_ci		cval |= UART_LCR_SPAR;
25908c2ecf20Sopenharmony_ci#endif
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci	return cval;
25938c2ecf20Sopenharmony_ci}
25948c2ecf20Sopenharmony_ci
25958c2ecf20Sopenharmony_civoid serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
25968c2ecf20Sopenharmony_ci			       unsigned int quot, unsigned int quot_frac)
25978c2ecf20Sopenharmony_ci{
25988c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_ci	/* Workaround to enable 115200 baud on OMAP1510 internal ports */
26018c2ecf20Sopenharmony_ci	if (is_omap1510_8250(up)) {
26028c2ecf20Sopenharmony_ci		if (baud == 115200) {
26038c2ecf20Sopenharmony_ci			quot = 1;
26048c2ecf20Sopenharmony_ci			serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
26058c2ecf20Sopenharmony_ci		} else
26068c2ecf20Sopenharmony_ci			serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
26078c2ecf20Sopenharmony_ci	}
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	/*
26108c2ecf20Sopenharmony_ci	 * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
26118c2ecf20Sopenharmony_ci	 * otherwise just set DLAB
26128c2ecf20Sopenharmony_ci	 */
26138c2ecf20Sopenharmony_ci	if (up->capabilities & UART_NATSEMI)
26148c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, 0xe0);
26158c2ecf20Sopenharmony_ci	else
26168c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci	serial_dl_write(up, quot);
26198c2ecf20Sopenharmony_ci}
26208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_set_divisor);
26218c2ecf20Sopenharmony_ci
26228c2ecf20Sopenharmony_cistatic void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
26238c2ecf20Sopenharmony_ci				   unsigned int quot, unsigned int quot_frac)
26248c2ecf20Sopenharmony_ci{
26258c2ecf20Sopenharmony_ci	if (port->set_divisor)
26268c2ecf20Sopenharmony_ci		port->set_divisor(port, baud, quot, quot_frac);
26278c2ecf20Sopenharmony_ci	else
26288c2ecf20Sopenharmony_ci		serial8250_do_set_divisor(port, baud, quot, quot_frac);
26298c2ecf20Sopenharmony_ci}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_cistatic unsigned int serial8250_get_baud_rate(struct uart_port *port,
26328c2ecf20Sopenharmony_ci					     struct ktermios *termios,
26338c2ecf20Sopenharmony_ci					     struct ktermios *old)
26348c2ecf20Sopenharmony_ci{
26358c2ecf20Sopenharmony_ci	unsigned int tolerance = port->uartclk / 100;
26368c2ecf20Sopenharmony_ci	unsigned int min;
26378c2ecf20Sopenharmony_ci	unsigned int max;
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	/*
26408c2ecf20Sopenharmony_ci	 * Handle magic divisors for baud rates above baud_base on SMSC
26418c2ecf20Sopenharmony_ci	 * Super I/O chips.  Enable custom rates of clk/4 and clk/8, but
26428c2ecf20Sopenharmony_ci	 * disable divisor values beyond 32767, which are unavailable.
26438c2ecf20Sopenharmony_ci	 */
26448c2ecf20Sopenharmony_ci	if (port->flags & UPF_MAGIC_MULTIPLIER) {
26458c2ecf20Sopenharmony_ci		min = port->uartclk / 16 / UART_DIV_MAX >> 1;
26468c2ecf20Sopenharmony_ci		max = (port->uartclk + tolerance) / 4;
26478c2ecf20Sopenharmony_ci	} else {
26488c2ecf20Sopenharmony_ci		min = port->uartclk / 16 / UART_DIV_MAX;
26498c2ecf20Sopenharmony_ci		max = (port->uartclk + tolerance) / 16;
26508c2ecf20Sopenharmony_ci	}
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	/*
26538c2ecf20Sopenharmony_ci	 * Ask the core to calculate the divisor for us.
26548c2ecf20Sopenharmony_ci	 * Allow 1% tolerance at the upper limit so uart clks marginally
26558c2ecf20Sopenharmony_ci	 * slower than nominal still match standard baud rates without
26568c2ecf20Sopenharmony_ci	 * causing transmission errors.
26578c2ecf20Sopenharmony_ci	 */
26588c2ecf20Sopenharmony_ci	return uart_get_baud_rate(port, termios, old, min, max);
26598c2ecf20Sopenharmony_ci}
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci/*
26628c2ecf20Sopenharmony_ci * Note in order to avoid the tty port mutex deadlock don't use the next method
26638c2ecf20Sopenharmony_ci * within the uart port callbacks. Primarily it's supposed to be utilized to
26648c2ecf20Sopenharmony_ci * handle a sudden reference clock rate change.
26658c2ecf20Sopenharmony_ci */
26668c2ecf20Sopenharmony_civoid serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
26678c2ecf20Sopenharmony_ci{
26688c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
26698c2ecf20Sopenharmony_ci	struct tty_port *tport = &port->state->port;
26708c2ecf20Sopenharmony_ci	unsigned int baud, quot, frac = 0;
26718c2ecf20Sopenharmony_ci	struct ktermios *termios;
26728c2ecf20Sopenharmony_ci	struct tty_struct *tty;
26738c2ecf20Sopenharmony_ci	unsigned long flags;
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	tty = tty_port_tty_get(tport);
26768c2ecf20Sopenharmony_ci	if (!tty) {
26778c2ecf20Sopenharmony_ci		mutex_lock(&tport->mutex);
26788c2ecf20Sopenharmony_ci		port->uartclk = uartclk;
26798c2ecf20Sopenharmony_ci		mutex_unlock(&tport->mutex);
26808c2ecf20Sopenharmony_ci		return;
26818c2ecf20Sopenharmony_ci	}
26828c2ecf20Sopenharmony_ci
26838c2ecf20Sopenharmony_ci	down_write(&tty->termios_rwsem);
26848c2ecf20Sopenharmony_ci	mutex_lock(&tport->mutex);
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	if (port->uartclk == uartclk)
26878c2ecf20Sopenharmony_ci		goto out_lock;
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_ci	port->uartclk = uartclk;
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_ci	if (!tty_port_initialized(tport))
26928c2ecf20Sopenharmony_ci		goto out_lock;
26938c2ecf20Sopenharmony_ci
26948c2ecf20Sopenharmony_ci	termios = &tty->termios;
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	baud = serial8250_get_baud_rate(port, termios, NULL);
26978c2ecf20Sopenharmony_ci	quot = serial8250_get_divisor(port, baud, &frac);
26988c2ecf20Sopenharmony_ci
26998c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
27008c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
27018c2ecf20Sopenharmony_ci
27028c2ecf20Sopenharmony_ci	uart_update_timeout(port, termios->c_cflag, baud);
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	serial8250_set_divisor(port, baud, quot, frac);
27058c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, up->lcr);
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
27088c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ciout_lock:
27118c2ecf20Sopenharmony_ci	mutex_unlock(&tport->mutex);
27128c2ecf20Sopenharmony_ci	up_write(&tty->termios_rwsem);
27138c2ecf20Sopenharmony_ci	tty_kref_put(tty);
27148c2ecf20Sopenharmony_ci}
27158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_update_uartclk);
27168c2ecf20Sopenharmony_ci
27178c2ecf20Sopenharmony_civoid
27188c2ecf20Sopenharmony_ciserial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
27198c2ecf20Sopenharmony_ci			  struct ktermios *old)
27208c2ecf20Sopenharmony_ci{
27218c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
27228c2ecf20Sopenharmony_ci	unsigned char cval;
27238c2ecf20Sopenharmony_ci	unsigned long flags;
27248c2ecf20Sopenharmony_ci	unsigned int baud, quot, frac = 0;
27258c2ecf20Sopenharmony_ci
27268c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_MINI) {
27278c2ecf20Sopenharmony_ci		termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR);
27288c2ecf20Sopenharmony_ci		if ((termios->c_cflag & CSIZE) == CS5 ||
27298c2ecf20Sopenharmony_ci		    (termios->c_cflag & CSIZE) == CS6)
27308c2ecf20Sopenharmony_ci			termios->c_cflag = (termios->c_cflag & ~CSIZE) | CS7;
27318c2ecf20Sopenharmony_ci	}
27328c2ecf20Sopenharmony_ci	cval = serial8250_compute_lcr(up, termios->c_cflag);
27338c2ecf20Sopenharmony_ci
27348c2ecf20Sopenharmony_ci	baud = serial8250_get_baud_rate(port, termios, old);
27358c2ecf20Sopenharmony_ci	quot = serial8250_get_divisor(port, baud, &frac);
27368c2ecf20Sopenharmony_ci
27378c2ecf20Sopenharmony_ci	/*
27388c2ecf20Sopenharmony_ci	 * Ok, we're now changing the port state.  Do it with
27398c2ecf20Sopenharmony_ci	 * interrupts disabled.
27408c2ecf20Sopenharmony_ci	 */
27418c2ecf20Sopenharmony_ci	serial8250_rpm_get(up);
27428c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, flags);
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci	up->lcr = cval;					/* Save computed LCR */
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
27478c2ecf20Sopenharmony_ci		if (baud < 2400 && !up->dma) {
27488c2ecf20Sopenharmony_ci			up->fcr &= ~UART_FCR_TRIGGER_MASK;
27498c2ecf20Sopenharmony_ci			up->fcr |= UART_FCR_TRIGGER_1;
27508c2ecf20Sopenharmony_ci		}
27518c2ecf20Sopenharmony_ci	}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ci	/*
27548c2ecf20Sopenharmony_ci	 * MCR-based auto flow control.  When AFE is enabled, RTS will be
27558c2ecf20Sopenharmony_ci	 * deasserted when the receive FIFO contains more characters than
27568c2ecf20Sopenharmony_ci	 * the trigger, or the MCR RTS bit is cleared.
27578c2ecf20Sopenharmony_ci	 */
27588c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_AFE) {
27598c2ecf20Sopenharmony_ci		up->mcr &= ~UART_MCR_AFE;
27608c2ecf20Sopenharmony_ci		if (termios->c_cflag & CRTSCTS)
27618c2ecf20Sopenharmony_ci			up->mcr |= UART_MCR_AFE;
27628c2ecf20Sopenharmony_ci	}
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci	/*
27658c2ecf20Sopenharmony_ci	 * Update the per-port timeout.
27668c2ecf20Sopenharmony_ci	 */
27678c2ecf20Sopenharmony_ci	uart_update_timeout(port, termios->c_cflag, baud);
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci	port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
27708c2ecf20Sopenharmony_ci	if (termios->c_iflag & INPCK)
27718c2ecf20Sopenharmony_ci		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
27728c2ecf20Sopenharmony_ci	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
27738c2ecf20Sopenharmony_ci		port->read_status_mask |= UART_LSR_BI;
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_ci	/*
27768c2ecf20Sopenharmony_ci	 * Characteres to ignore
27778c2ecf20Sopenharmony_ci	 */
27788c2ecf20Sopenharmony_ci	port->ignore_status_mask = 0;
27798c2ecf20Sopenharmony_ci	if (termios->c_iflag & IGNPAR)
27808c2ecf20Sopenharmony_ci		port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
27818c2ecf20Sopenharmony_ci	if (termios->c_iflag & IGNBRK) {
27828c2ecf20Sopenharmony_ci		port->ignore_status_mask |= UART_LSR_BI;
27838c2ecf20Sopenharmony_ci		/*
27848c2ecf20Sopenharmony_ci		 * If we're ignoring parity and break indicators,
27858c2ecf20Sopenharmony_ci		 * ignore overruns too (for real raw support).
27868c2ecf20Sopenharmony_ci		 */
27878c2ecf20Sopenharmony_ci		if (termios->c_iflag & IGNPAR)
27888c2ecf20Sopenharmony_ci			port->ignore_status_mask |= UART_LSR_OE;
27898c2ecf20Sopenharmony_ci	}
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci	/*
27928c2ecf20Sopenharmony_ci	 * ignore all characters if CREAD is not set
27938c2ecf20Sopenharmony_ci	 */
27948c2ecf20Sopenharmony_ci	if ((termios->c_cflag & CREAD) == 0)
27958c2ecf20Sopenharmony_ci		port->ignore_status_mask |= UART_LSR_DR;
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	/*
27988c2ecf20Sopenharmony_ci	 * CTS flow control flag and modem status interrupts
27998c2ecf20Sopenharmony_ci	 */
28008c2ecf20Sopenharmony_ci	up->ier &= ~UART_IER_MSI;
28018c2ecf20Sopenharmony_ci	if (!(up->bugs & UART_BUG_NOMSR) &&
28028c2ecf20Sopenharmony_ci			UART_ENABLE_MS(&up->port, termios->c_cflag))
28038c2ecf20Sopenharmony_ci		up->ier |= UART_IER_MSI;
28048c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_UUE)
28058c2ecf20Sopenharmony_ci		up->ier |= UART_IER_UUE;
28068c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_RTOIE)
28078c2ecf20Sopenharmony_ci		up->ier |= UART_IER_RTOIE;
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, up->ier);
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_EFR) {
28128c2ecf20Sopenharmony_ci		unsigned char efr = 0;
28138c2ecf20Sopenharmony_ci		/*
28148c2ecf20Sopenharmony_ci		 * TI16C752/Startech hardware flow control.  FIXME:
28158c2ecf20Sopenharmony_ci		 * - TI16C752 requires control thresholds to be set.
28168c2ecf20Sopenharmony_ci		 * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
28178c2ecf20Sopenharmony_ci		 */
28188c2ecf20Sopenharmony_ci		if (termios->c_cflag & CRTSCTS)
28198c2ecf20Sopenharmony_ci			efr |= UART_EFR_CTS;
28208c2ecf20Sopenharmony_ci
28218c2ecf20Sopenharmony_ci		serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
28228c2ecf20Sopenharmony_ci		if (port->flags & UPF_EXAR_EFR)
28238c2ecf20Sopenharmony_ci			serial_port_out(port, UART_XR_EFR, efr);
28248c2ecf20Sopenharmony_ci		else
28258c2ecf20Sopenharmony_ci			serial_port_out(port, UART_EFR, efr);
28268c2ecf20Sopenharmony_ci	}
28278c2ecf20Sopenharmony_ci
28288c2ecf20Sopenharmony_ci	serial8250_set_divisor(port, baud, quot, frac);
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci	/*
28318c2ecf20Sopenharmony_ci	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
28328c2ecf20Sopenharmony_ci	 * is written without DLAB set, this mode will be disabled.
28338c2ecf20Sopenharmony_ci	 */
28348c2ecf20Sopenharmony_ci	if (port->type == PORT_16750)
28358c2ecf20Sopenharmony_ci		serial_port_out(port, UART_FCR, up->fcr);
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, up->lcr);	/* reset DLAB */
28388c2ecf20Sopenharmony_ci	if (port->type != PORT_16750) {
28398c2ecf20Sopenharmony_ci		/* emulated UARTs (Lucent Venus 167x) need two steps */
28408c2ecf20Sopenharmony_ci		if (up->fcr & UART_FCR_ENABLE_FIFO)
28418c2ecf20Sopenharmony_ci			serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
28428c2ecf20Sopenharmony_ci		serial_port_out(port, UART_FCR, up->fcr);	/* set fcr */
28438c2ecf20Sopenharmony_ci	}
28448c2ecf20Sopenharmony_ci	serial8250_set_mctrl(port, port->mctrl);
28458c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, flags);
28468c2ecf20Sopenharmony_ci	serial8250_rpm_put(up);
28478c2ecf20Sopenharmony_ci
28488c2ecf20Sopenharmony_ci	/* Don't rewrite B0 */
28498c2ecf20Sopenharmony_ci	if (tty_termios_baud_rate(termios))
28508c2ecf20Sopenharmony_ci		tty_termios_encode_baud_rate(termios, baud, baud);
28518c2ecf20Sopenharmony_ci}
28528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(serial8250_do_set_termios);
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_cistatic void
28558c2ecf20Sopenharmony_ciserial8250_set_termios(struct uart_port *port, struct ktermios *termios,
28568c2ecf20Sopenharmony_ci		       struct ktermios *old)
28578c2ecf20Sopenharmony_ci{
28588c2ecf20Sopenharmony_ci	if (port->set_termios)
28598c2ecf20Sopenharmony_ci		port->set_termios(port, termios, old);
28608c2ecf20Sopenharmony_ci	else
28618c2ecf20Sopenharmony_ci		serial8250_do_set_termios(port, termios, old);
28628c2ecf20Sopenharmony_ci}
28638c2ecf20Sopenharmony_ci
28648c2ecf20Sopenharmony_civoid serial8250_do_set_ldisc(struct uart_port *port, struct ktermios *termios)
28658c2ecf20Sopenharmony_ci{
28668c2ecf20Sopenharmony_ci	if (termios->c_line == N_PPS) {
28678c2ecf20Sopenharmony_ci		port->flags |= UPF_HARDPPS_CD;
28688c2ecf20Sopenharmony_ci		spin_lock_irq(&port->lock);
28698c2ecf20Sopenharmony_ci		serial8250_enable_ms(port);
28708c2ecf20Sopenharmony_ci		spin_unlock_irq(&port->lock);
28718c2ecf20Sopenharmony_ci	} else {
28728c2ecf20Sopenharmony_ci		port->flags &= ~UPF_HARDPPS_CD;
28738c2ecf20Sopenharmony_ci		if (!UART_ENABLE_MS(port, termios->c_cflag)) {
28748c2ecf20Sopenharmony_ci			spin_lock_irq(&port->lock);
28758c2ecf20Sopenharmony_ci			serial8250_disable_ms(port);
28768c2ecf20Sopenharmony_ci			spin_unlock_irq(&port->lock);
28778c2ecf20Sopenharmony_ci		}
28788c2ecf20Sopenharmony_ci	}
28798c2ecf20Sopenharmony_ci}
28808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_do_set_ldisc);
28818c2ecf20Sopenharmony_ci
28828c2ecf20Sopenharmony_cistatic void
28838c2ecf20Sopenharmony_ciserial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
28848c2ecf20Sopenharmony_ci{
28858c2ecf20Sopenharmony_ci	if (port->set_ldisc)
28868c2ecf20Sopenharmony_ci		port->set_ldisc(port, termios);
28878c2ecf20Sopenharmony_ci	else
28888c2ecf20Sopenharmony_ci		serial8250_do_set_ldisc(port, termios);
28898c2ecf20Sopenharmony_ci}
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_civoid serial8250_do_pm(struct uart_port *port, unsigned int state,
28928c2ecf20Sopenharmony_ci		      unsigned int oldstate)
28938c2ecf20Sopenharmony_ci{
28948c2ecf20Sopenharmony_ci	struct uart_8250_port *p = up_to_u8250p(port);
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	serial8250_set_sleep(p, state != 0);
28978c2ecf20Sopenharmony_ci}
28988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(serial8250_do_pm);
28998c2ecf20Sopenharmony_ci
29008c2ecf20Sopenharmony_cistatic void
29018c2ecf20Sopenharmony_ciserial8250_pm(struct uart_port *port, unsigned int state,
29028c2ecf20Sopenharmony_ci	      unsigned int oldstate)
29038c2ecf20Sopenharmony_ci{
29048c2ecf20Sopenharmony_ci	if (port->pm)
29058c2ecf20Sopenharmony_ci		port->pm(port, state, oldstate);
29068c2ecf20Sopenharmony_ci	else
29078c2ecf20Sopenharmony_ci		serial8250_do_pm(port, state, oldstate);
29088c2ecf20Sopenharmony_ci}
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_cistatic unsigned int serial8250_port_size(struct uart_8250_port *pt)
29118c2ecf20Sopenharmony_ci{
29128c2ecf20Sopenharmony_ci	if (pt->port.mapsize)
29138c2ecf20Sopenharmony_ci		return pt->port.mapsize;
29148c2ecf20Sopenharmony_ci	if (pt->port.iotype == UPIO_AU) {
29158c2ecf20Sopenharmony_ci		if (pt->port.type == PORT_RT2880)
29168c2ecf20Sopenharmony_ci			return 0x100;
29178c2ecf20Sopenharmony_ci		return 0x1000;
29188c2ecf20Sopenharmony_ci	}
29198c2ecf20Sopenharmony_ci	if (is_omap1_8250(pt))
29208c2ecf20Sopenharmony_ci		return 0x16 << pt->port.regshift;
29218c2ecf20Sopenharmony_ci
29228c2ecf20Sopenharmony_ci	return 8 << pt->port.regshift;
29238c2ecf20Sopenharmony_ci}
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci/*
29268c2ecf20Sopenharmony_ci * Resource handling.
29278c2ecf20Sopenharmony_ci */
29288c2ecf20Sopenharmony_cistatic int serial8250_request_std_resource(struct uart_8250_port *up)
29298c2ecf20Sopenharmony_ci{
29308c2ecf20Sopenharmony_ci	unsigned int size = serial8250_port_size(up);
29318c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
29328c2ecf20Sopenharmony_ci	int ret = 0;
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_ci	switch (port->iotype) {
29358c2ecf20Sopenharmony_ci	case UPIO_AU:
29368c2ecf20Sopenharmony_ci	case UPIO_TSI:
29378c2ecf20Sopenharmony_ci	case UPIO_MEM32:
29388c2ecf20Sopenharmony_ci	case UPIO_MEM32BE:
29398c2ecf20Sopenharmony_ci	case UPIO_MEM16:
29408c2ecf20Sopenharmony_ci	case UPIO_MEM:
29418c2ecf20Sopenharmony_ci		if (!port->mapbase) {
29428c2ecf20Sopenharmony_ci			ret = -EINVAL;
29438c2ecf20Sopenharmony_ci			break;
29448c2ecf20Sopenharmony_ci		}
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci		if (!request_mem_region(port->mapbase, size, "serial")) {
29478c2ecf20Sopenharmony_ci			ret = -EBUSY;
29488c2ecf20Sopenharmony_ci			break;
29498c2ecf20Sopenharmony_ci		}
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci		if (port->flags & UPF_IOREMAP) {
29528c2ecf20Sopenharmony_ci			port->membase = ioremap(port->mapbase, size);
29538c2ecf20Sopenharmony_ci			if (!port->membase) {
29548c2ecf20Sopenharmony_ci				release_mem_region(port->mapbase, size);
29558c2ecf20Sopenharmony_ci				ret = -ENOMEM;
29568c2ecf20Sopenharmony_ci			}
29578c2ecf20Sopenharmony_ci		}
29588c2ecf20Sopenharmony_ci		break;
29598c2ecf20Sopenharmony_ci
29608c2ecf20Sopenharmony_ci	case UPIO_HUB6:
29618c2ecf20Sopenharmony_ci	case UPIO_PORT:
29628c2ecf20Sopenharmony_ci		if (!request_region(port->iobase, size, "serial"))
29638c2ecf20Sopenharmony_ci			ret = -EBUSY;
29648c2ecf20Sopenharmony_ci		break;
29658c2ecf20Sopenharmony_ci	}
29668c2ecf20Sopenharmony_ci	return ret;
29678c2ecf20Sopenharmony_ci}
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_cistatic void serial8250_release_std_resource(struct uart_8250_port *up)
29708c2ecf20Sopenharmony_ci{
29718c2ecf20Sopenharmony_ci	unsigned int size = serial8250_port_size(up);
29728c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci	switch (port->iotype) {
29758c2ecf20Sopenharmony_ci	case UPIO_AU:
29768c2ecf20Sopenharmony_ci	case UPIO_TSI:
29778c2ecf20Sopenharmony_ci	case UPIO_MEM32:
29788c2ecf20Sopenharmony_ci	case UPIO_MEM32BE:
29798c2ecf20Sopenharmony_ci	case UPIO_MEM16:
29808c2ecf20Sopenharmony_ci	case UPIO_MEM:
29818c2ecf20Sopenharmony_ci		if (!port->mapbase)
29828c2ecf20Sopenharmony_ci			break;
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci		if (port->flags & UPF_IOREMAP) {
29858c2ecf20Sopenharmony_ci			iounmap(port->membase);
29868c2ecf20Sopenharmony_ci			port->membase = NULL;
29878c2ecf20Sopenharmony_ci		}
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci		release_mem_region(port->mapbase, size);
29908c2ecf20Sopenharmony_ci		break;
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci	case UPIO_HUB6:
29938c2ecf20Sopenharmony_ci	case UPIO_PORT:
29948c2ecf20Sopenharmony_ci		release_region(port->iobase, size);
29958c2ecf20Sopenharmony_ci		break;
29968c2ecf20Sopenharmony_ci	}
29978c2ecf20Sopenharmony_ci}
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_cistatic void serial8250_release_port(struct uart_port *port)
30008c2ecf20Sopenharmony_ci{
30018c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_ci	serial8250_release_std_resource(up);
30048c2ecf20Sopenharmony_ci}
30058c2ecf20Sopenharmony_ci
30068c2ecf20Sopenharmony_cistatic int serial8250_request_port(struct uart_port *port)
30078c2ecf20Sopenharmony_ci{
30088c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
30098c2ecf20Sopenharmony_ci
30108c2ecf20Sopenharmony_ci	return serial8250_request_std_resource(up);
30118c2ecf20Sopenharmony_ci}
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_cistatic int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
30148c2ecf20Sopenharmony_ci{
30158c2ecf20Sopenharmony_ci	const struct serial8250_config *conf_type = &uart_config[up->port.type];
30168c2ecf20Sopenharmony_ci	unsigned char bytes;
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci	return bytes ? bytes : -EOPNOTSUPP;
30218c2ecf20Sopenharmony_ci}
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_cistatic int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
30248c2ecf20Sopenharmony_ci{
30258c2ecf20Sopenharmony_ci	const struct serial8250_config *conf_type = &uart_config[up->port.type];
30268c2ecf20Sopenharmony_ci	int i;
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
30298c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci	for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
30328c2ecf20Sopenharmony_ci		if (bytes < conf_type->rxtrig_bytes[i])
30338c2ecf20Sopenharmony_ci			/* Use the nearest lower value */
30348c2ecf20Sopenharmony_ci			return (--i) << UART_FCR_R_TRIG_SHIFT;
30358c2ecf20Sopenharmony_ci	}
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci	return UART_FCR_R_TRIG_11;
30388c2ecf20Sopenharmony_ci}
30398c2ecf20Sopenharmony_ci
30408c2ecf20Sopenharmony_cistatic int do_get_rxtrig(struct tty_port *port)
30418c2ecf20Sopenharmony_ci{
30428c2ecf20Sopenharmony_ci	struct uart_state *state = container_of(port, struct uart_state, port);
30438c2ecf20Sopenharmony_ci	struct uart_port *uport = state->uart_port;
30448c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(uport);
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_ci	if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
30478c2ecf20Sopenharmony_ci		return -EINVAL;
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci	return fcr_get_rxtrig_bytes(up);
30508c2ecf20Sopenharmony_ci}
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_cistatic int do_serial8250_get_rxtrig(struct tty_port *port)
30538c2ecf20Sopenharmony_ci{
30548c2ecf20Sopenharmony_ci	int rxtrig_bytes;
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	mutex_lock(&port->mutex);
30578c2ecf20Sopenharmony_ci	rxtrig_bytes = do_get_rxtrig(port);
30588c2ecf20Sopenharmony_ci	mutex_unlock(&port->mutex);
30598c2ecf20Sopenharmony_ci
30608c2ecf20Sopenharmony_ci	return rxtrig_bytes;
30618c2ecf20Sopenharmony_ci}
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_cistatic ssize_t rx_trig_bytes_show(struct device *dev,
30648c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)
30658c2ecf20Sopenharmony_ci{
30668c2ecf20Sopenharmony_ci	struct tty_port *port = dev_get_drvdata(dev);
30678c2ecf20Sopenharmony_ci	int rxtrig_bytes;
30688c2ecf20Sopenharmony_ci
30698c2ecf20Sopenharmony_ci	rxtrig_bytes = do_serial8250_get_rxtrig(port);
30708c2ecf20Sopenharmony_ci	if (rxtrig_bytes < 0)
30718c2ecf20Sopenharmony_ci		return rxtrig_bytes;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci	return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
30748c2ecf20Sopenharmony_ci}
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_cistatic int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
30778c2ecf20Sopenharmony_ci{
30788c2ecf20Sopenharmony_ci	struct uart_state *state = container_of(port, struct uart_state, port);
30798c2ecf20Sopenharmony_ci	struct uart_port *uport = state->uart_port;
30808c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(uport);
30818c2ecf20Sopenharmony_ci	int rxtrig;
30828c2ecf20Sopenharmony_ci
30838c2ecf20Sopenharmony_ci	if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
30848c2ecf20Sopenharmony_ci		return -EINVAL;
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	rxtrig = bytes_to_fcr_rxtrig(up, bytes);
30878c2ecf20Sopenharmony_ci	if (rxtrig < 0)
30888c2ecf20Sopenharmony_ci		return rxtrig;
30898c2ecf20Sopenharmony_ci
30908c2ecf20Sopenharmony_ci	serial8250_clear_fifos(up);
30918c2ecf20Sopenharmony_ci	up->fcr &= ~UART_FCR_TRIGGER_MASK;
30928c2ecf20Sopenharmony_ci	up->fcr |= (unsigned char)rxtrig;
30938c2ecf20Sopenharmony_ci	serial_out(up, UART_FCR, up->fcr);
30948c2ecf20Sopenharmony_ci	return 0;
30958c2ecf20Sopenharmony_ci}
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_cistatic int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
30988c2ecf20Sopenharmony_ci{
30998c2ecf20Sopenharmony_ci	int ret;
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_ci	mutex_lock(&port->mutex);
31028c2ecf20Sopenharmony_ci	ret = do_set_rxtrig(port, bytes);
31038c2ecf20Sopenharmony_ci	mutex_unlock(&port->mutex);
31048c2ecf20Sopenharmony_ci
31058c2ecf20Sopenharmony_ci	return ret;
31068c2ecf20Sopenharmony_ci}
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_cistatic ssize_t rx_trig_bytes_store(struct device *dev,
31098c2ecf20Sopenharmony_ci	struct device_attribute *attr, const char *buf, size_t count)
31108c2ecf20Sopenharmony_ci{
31118c2ecf20Sopenharmony_ci	struct tty_port *port = dev_get_drvdata(dev);
31128c2ecf20Sopenharmony_ci	unsigned char bytes;
31138c2ecf20Sopenharmony_ci	int ret;
31148c2ecf20Sopenharmony_ci
31158c2ecf20Sopenharmony_ci	if (!count)
31168c2ecf20Sopenharmony_ci		return -EINVAL;
31178c2ecf20Sopenharmony_ci
31188c2ecf20Sopenharmony_ci	ret = kstrtou8(buf, 10, &bytes);
31198c2ecf20Sopenharmony_ci	if (ret < 0)
31208c2ecf20Sopenharmony_ci		return ret;
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	ret = do_serial8250_set_rxtrig(port, bytes);
31238c2ecf20Sopenharmony_ci	if (ret < 0)
31248c2ecf20Sopenharmony_ci		return ret;
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	return count;
31278c2ecf20Sopenharmony_ci}
31288c2ecf20Sopenharmony_ci
31298c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(rx_trig_bytes);
31308c2ecf20Sopenharmony_ci
31318c2ecf20Sopenharmony_cistatic struct attribute *serial8250_dev_attrs[] = {
31328c2ecf20Sopenharmony_ci	&dev_attr_rx_trig_bytes.attr,
31338c2ecf20Sopenharmony_ci	NULL
31348c2ecf20Sopenharmony_ci};
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_cistatic struct attribute_group serial8250_dev_attr_group = {
31378c2ecf20Sopenharmony_ci	.attrs = serial8250_dev_attrs,
31388c2ecf20Sopenharmony_ci};
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_cistatic void register_dev_spec_attr_grp(struct uart_8250_port *up)
31418c2ecf20Sopenharmony_ci{
31428c2ecf20Sopenharmony_ci	const struct serial8250_config *conf_type = &uart_config[up->port.type];
31438c2ecf20Sopenharmony_ci
31448c2ecf20Sopenharmony_ci	if (conf_type->rxtrig_bytes[0])
31458c2ecf20Sopenharmony_ci		up->port.attr_group = &serial8250_dev_attr_group;
31468c2ecf20Sopenharmony_ci}
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_cistatic void serial8250_config_port(struct uart_port *port, int flags)
31498c2ecf20Sopenharmony_ci{
31508c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
31518c2ecf20Sopenharmony_ci	int ret;
31528c2ecf20Sopenharmony_ci
31538c2ecf20Sopenharmony_ci	/*
31548c2ecf20Sopenharmony_ci	 * Find the region that we can probe for.  This in turn
31558c2ecf20Sopenharmony_ci	 * tells us whether we can probe for the type of port.
31568c2ecf20Sopenharmony_ci	 */
31578c2ecf20Sopenharmony_ci	ret = serial8250_request_std_resource(up);
31588c2ecf20Sopenharmony_ci	if (ret < 0)
31598c2ecf20Sopenharmony_ci		return;
31608c2ecf20Sopenharmony_ci
31618c2ecf20Sopenharmony_ci	if (port->iotype != up->cur_iotype)
31628c2ecf20Sopenharmony_ci		set_io_from_upio(port);
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci	if (flags & UART_CONFIG_TYPE)
31658c2ecf20Sopenharmony_ci		autoconfig(up);
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	/* if access method is AU, it is a 16550 with a quirk */
31688c2ecf20Sopenharmony_ci	if (port->type == PORT_16550A && port->iotype == UPIO_AU)
31698c2ecf20Sopenharmony_ci		up->bugs |= UART_BUG_NOMSR;
31708c2ecf20Sopenharmony_ci
31718c2ecf20Sopenharmony_ci	/* HW bugs may trigger IRQ while IIR == NO_INT */
31728c2ecf20Sopenharmony_ci	if (port->type == PORT_TEGRA)
31738c2ecf20Sopenharmony_ci		up->bugs |= UART_BUG_NOMSR;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
31768c2ecf20Sopenharmony_ci		autoconfig_irq(up);
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (port->type == PORT_UNKNOWN)
31798c2ecf20Sopenharmony_ci		serial8250_release_std_resource(up);
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	register_dev_spec_attr_grp(up);
31828c2ecf20Sopenharmony_ci	up->fcr = uart_config[up->port.type].fcr;
31838c2ecf20Sopenharmony_ci}
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_cistatic int
31868c2ecf20Sopenharmony_ciserial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
31878c2ecf20Sopenharmony_ci{
31888c2ecf20Sopenharmony_ci	if (ser->irq >= nr_irqs || ser->irq < 0 ||
31898c2ecf20Sopenharmony_ci	    ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
31908c2ecf20Sopenharmony_ci	    ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
31918c2ecf20Sopenharmony_ci	    ser->type == PORT_STARTECH)
31928c2ecf20Sopenharmony_ci		return -EINVAL;
31938c2ecf20Sopenharmony_ci	return 0;
31948c2ecf20Sopenharmony_ci}
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_cistatic const char *serial8250_type(struct uart_port *port)
31978c2ecf20Sopenharmony_ci{
31988c2ecf20Sopenharmony_ci	int type = port->type;
31998c2ecf20Sopenharmony_ci
32008c2ecf20Sopenharmony_ci	if (type >= ARRAY_SIZE(uart_config))
32018c2ecf20Sopenharmony_ci		type = 0;
32028c2ecf20Sopenharmony_ci	return uart_config[type].name;
32038c2ecf20Sopenharmony_ci}
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_cistatic const struct uart_ops serial8250_pops = {
32068c2ecf20Sopenharmony_ci	.tx_empty	= serial8250_tx_empty,
32078c2ecf20Sopenharmony_ci	.set_mctrl	= serial8250_set_mctrl,
32088c2ecf20Sopenharmony_ci	.get_mctrl	= serial8250_get_mctrl,
32098c2ecf20Sopenharmony_ci	.stop_tx	= serial8250_stop_tx,
32108c2ecf20Sopenharmony_ci	.start_tx	= serial8250_start_tx,
32118c2ecf20Sopenharmony_ci	.throttle	= serial8250_throttle,
32128c2ecf20Sopenharmony_ci	.unthrottle	= serial8250_unthrottle,
32138c2ecf20Sopenharmony_ci	.stop_rx	= serial8250_stop_rx,
32148c2ecf20Sopenharmony_ci	.enable_ms	= serial8250_enable_ms,
32158c2ecf20Sopenharmony_ci	.break_ctl	= serial8250_break_ctl,
32168c2ecf20Sopenharmony_ci	.startup	= serial8250_startup,
32178c2ecf20Sopenharmony_ci	.shutdown	= serial8250_shutdown,
32188c2ecf20Sopenharmony_ci	.set_termios	= serial8250_set_termios,
32198c2ecf20Sopenharmony_ci	.set_ldisc	= serial8250_set_ldisc,
32208c2ecf20Sopenharmony_ci	.pm		= serial8250_pm,
32218c2ecf20Sopenharmony_ci	.type		= serial8250_type,
32228c2ecf20Sopenharmony_ci	.release_port	= serial8250_release_port,
32238c2ecf20Sopenharmony_ci	.request_port	= serial8250_request_port,
32248c2ecf20Sopenharmony_ci	.config_port	= serial8250_config_port,
32258c2ecf20Sopenharmony_ci	.verify_port	= serial8250_verify_port,
32268c2ecf20Sopenharmony_ci#ifdef CONFIG_CONSOLE_POLL
32278c2ecf20Sopenharmony_ci	.poll_get_char = serial8250_get_poll_char,
32288c2ecf20Sopenharmony_ci	.poll_put_char = serial8250_put_poll_char,
32298c2ecf20Sopenharmony_ci#endif
32308c2ecf20Sopenharmony_ci};
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_civoid serial8250_init_port(struct uart_8250_port *up)
32338c2ecf20Sopenharmony_ci{
32348c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	spin_lock_init(&port->lock);
32378c2ecf20Sopenharmony_ci	port->pm = NULL;
32388c2ecf20Sopenharmony_ci	port->ops = &serial8250_pops;
32398c2ecf20Sopenharmony_ci	port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	up->cur_iotype = 0xFF;
32428c2ecf20Sopenharmony_ci}
32438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_init_port);
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_civoid serial8250_set_defaults(struct uart_8250_port *up)
32468c2ecf20Sopenharmony_ci{
32478c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	if (up->port.flags & UPF_FIXED_TYPE) {
32508c2ecf20Sopenharmony_ci		unsigned int type = up->port.type;
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci		if (!up->port.fifosize)
32538c2ecf20Sopenharmony_ci			up->port.fifosize = uart_config[type].fifo_size;
32548c2ecf20Sopenharmony_ci		if (!up->tx_loadsz)
32558c2ecf20Sopenharmony_ci			up->tx_loadsz = uart_config[type].tx_loadsz;
32568c2ecf20Sopenharmony_ci		if (!up->capabilities)
32578c2ecf20Sopenharmony_ci			up->capabilities = uart_config[type].flags;
32588c2ecf20Sopenharmony_ci	}
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_ci	set_io_from_upio(port);
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_ci	/* default dma handlers */
32638c2ecf20Sopenharmony_ci	if (up->dma) {
32648c2ecf20Sopenharmony_ci		if (!up->dma->tx_dma)
32658c2ecf20Sopenharmony_ci			up->dma->tx_dma = serial8250_tx_dma;
32668c2ecf20Sopenharmony_ci		if (!up->dma->rx_dma)
32678c2ecf20Sopenharmony_ci			up->dma->rx_dma = serial8250_rx_dma;
32688c2ecf20Sopenharmony_ci	}
32698c2ecf20Sopenharmony_ci}
32708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(serial8250_set_defaults);
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci#ifdef CONFIG_SERIAL_8250_CONSOLE
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_cistatic void serial8250_console_putchar(struct uart_port *port, int ch)
32758c2ecf20Sopenharmony_ci{
32768c2ecf20Sopenharmony_ci	struct uart_8250_port *up = up_to_u8250p(port);
32778c2ecf20Sopenharmony_ci
32788c2ecf20Sopenharmony_ci	wait_for_xmitr(up, UART_LSR_THRE);
32798c2ecf20Sopenharmony_ci	serial_port_out(port, UART_TX, ch);
32808c2ecf20Sopenharmony_ci}
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci/*
32838c2ecf20Sopenharmony_ci *	Restore serial console when h/w power-off detected
32848c2ecf20Sopenharmony_ci */
32858c2ecf20Sopenharmony_cistatic void serial8250_console_restore(struct uart_8250_port *up)
32868c2ecf20Sopenharmony_ci{
32878c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
32888c2ecf20Sopenharmony_ci	struct ktermios termios;
32898c2ecf20Sopenharmony_ci	unsigned int baud, quot, frac = 0;
32908c2ecf20Sopenharmony_ci
32918c2ecf20Sopenharmony_ci	termios.c_cflag = port->cons->cflag;
32928c2ecf20Sopenharmony_ci	termios.c_ispeed = port->cons->ispeed;
32938c2ecf20Sopenharmony_ci	termios.c_ospeed = port->cons->ospeed;
32948c2ecf20Sopenharmony_ci	if (port->state->port.tty && termios.c_cflag == 0) {
32958c2ecf20Sopenharmony_ci		termios.c_cflag = port->state->port.tty->termios.c_cflag;
32968c2ecf20Sopenharmony_ci		termios.c_ispeed = port->state->port.tty->termios.c_ispeed;
32978c2ecf20Sopenharmony_ci		termios.c_ospeed = port->state->port.tty->termios.c_ospeed;
32988c2ecf20Sopenharmony_ci	}
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci	baud = serial8250_get_baud_rate(port, &termios, NULL);
33018c2ecf20Sopenharmony_ci	quot = serial8250_get_divisor(port, baud, &frac);
33028c2ecf20Sopenharmony_ci
33038c2ecf20Sopenharmony_ci	serial8250_set_divisor(port, baud, quot, frac);
33048c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, up->lcr);
33058c2ecf20Sopenharmony_ci	serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
33068c2ecf20Sopenharmony_ci}
33078c2ecf20Sopenharmony_ci
33088c2ecf20Sopenharmony_ci/*
33098c2ecf20Sopenharmony_ci *	Print a string to the serial port trying not to disturb
33108c2ecf20Sopenharmony_ci *	any possible real use of the port...
33118c2ecf20Sopenharmony_ci *
33128c2ecf20Sopenharmony_ci *	The console_lock must be held when we get here.
33138c2ecf20Sopenharmony_ci *
33148c2ecf20Sopenharmony_ci *	Doing runtime PM is really a bad idea for the kernel console.
33158c2ecf20Sopenharmony_ci *	Thus, we assume the function is called when device is powered up.
33168c2ecf20Sopenharmony_ci */
33178c2ecf20Sopenharmony_civoid serial8250_console_write(struct uart_8250_port *up, const char *s,
33188c2ecf20Sopenharmony_ci			      unsigned int count)
33198c2ecf20Sopenharmony_ci{
33208c2ecf20Sopenharmony_ci	struct uart_8250_em485 *em485 = up->em485;
33218c2ecf20Sopenharmony_ci	struct uart_port *port = &up->port;
33228c2ecf20Sopenharmony_ci	unsigned long flags;
33238c2ecf20Sopenharmony_ci	unsigned int ier;
33248c2ecf20Sopenharmony_ci	int locked = 1;
33258c2ecf20Sopenharmony_ci
33268c2ecf20Sopenharmony_ci	touch_nmi_watchdog();
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci	if (oops_in_progress)
33298c2ecf20Sopenharmony_ci		locked = spin_trylock_irqsave(&port->lock, flags);
33308c2ecf20Sopenharmony_ci	else
33318c2ecf20Sopenharmony_ci		spin_lock_irqsave(&port->lock, flags);
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	/*
33348c2ecf20Sopenharmony_ci	 *	First save the IER then disable the interrupts
33358c2ecf20Sopenharmony_ci	 */
33368c2ecf20Sopenharmony_ci	ier = serial_port_in(port, UART_IER);
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	if (up->capabilities & UART_CAP_UUE)
33398c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, UART_IER_UUE);
33408c2ecf20Sopenharmony_ci	else
33418c2ecf20Sopenharmony_ci		serial_port_out(port, UART_IER, 0);
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	/* check scratch reg to see if port powered off during system sleep */
33448c2ecf20Sopenharmony_ci	if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
33458c2ecf20Sopenharmony_ci		serial8250_console_restore(up);
33468c2ecf20Sopenharmony_ci		up->canary = 0;
33478c2ecf20Sopenharmony_ci	}
33488c2ecf20Sopenharmony_ci
33498c2ecf20Sopenharmony_ci	if (em485) {
33508c2ecf20Sopenharmony_ci		if (em485->tx_stopped)
33518c2ecf20Sopenharmony_ci			up->rs485_start_tx(up);
33528c2ecf20Sopenharmony_ci		mdelay(port->rs485.delay_rts_before_send);
33538c2ecf20Sopenharmony_ci	}
33548c2ecf20Sopenharmony_ci
33558c2ecf20Sopenharmony_ci	uart_console_write(port, s, count, serial8250_console_putchar);
33568c2ecf20Sopenharmony_ci
33578c2ecf20Sopenharmony_ci	/*
33588c2ecf20Sopenharmony_ci	 *	Finally, wait for transmitter to become empty
33598c2ecf20Sopenharmony_ci	 *	and restore the IER
33608c2ecf20Sopenharmony_ci	 */
33618c2ecf20Sopenharmony_ci	wait_for_xmitr(up, BOTH_EMPTY);
33628c2ecf20Sopenharmony_ci
33638c2ecf20Sopenharmony_ci	if (em485) {
33648c2ecf20Sopenharmony_ci		mdelay(port->rs485.delay_rts_after_send);
33658c2ecf20Sopenharmony_ci		if (em485->tx_stopped)
33668c2ecf20Sopenharmony_ci			up->rs485_stop_tx(up);
33678c2ecf20Sopenharmony_ci	}
33688c2ecf20Sopenharmony_ci
33698c2ecf20Sopenharmony_ci	serial_port_out(port, UART_IER, ier);
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	/*
33728c2ecf20Sopenharmony_ci	 *	The receive handling will happen properly because the
33738c2ecf20Sopenharmony_ci	 *	receive ready bit will still be set; it is not cleared
33748c2ecf20Sopenharmony_ci	 *	on read.  However, modem control will not, we must
33758c2ecf20Sopenharmony_ci	 *	call it if we have saved something in the saved flags
33768c2ecf20Sopenharmony_ci	 *	while processing with interrupts off.
33778c2ecf20Sopenharmony_ci	 */
33788c2ecf20Sopenharmony_ci	if (up->msr_saved_flags)
33798c2ecf20Sopenharmony_ci		serial8250_modem_status(up);
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci	if (locked)
33828c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&port->lock, flags);
33838c2ecf20Sopenharmony_ci}
33848c2ecf20Sopenharmony_ci
33858c2ecf20Sopenharmony_cistatic unsigned int probe_baud(struct uart_port *port)
33868c2ecf20Sopenharmony_ci{
33878c2ecf20Sopenharmony_ci	unsigned char lcr, dll, dlm;
33888c2ecf20Sopenharmony_ci	unsigned int quot;
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_ci	lcr = serial_port_in(port, UART_LCR);
33918c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
33928c2ecf20Sopenharmony_ci	dll = serial_port_in(port, UART_DLL);
33938c2ecf20Sopenharmony_ci	dlm = serial_port_in(port, UART_DLM);
33948c2ecf20Sopenharmony_ci	serial_port_out(port, UART_LCR, lcr);
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci	quot = (dlm << 8) | dll;
33978c2ecf20Sopenharmony_ci	return (port->uartclk / 16) / quot;
33988c2ecf20Sopenharmony_ci}
33998c2ecf20Sopenharmony_ci
34008c2ecf20Sopenharmony_ciint serial8250_console_setup(struct uart_port *port, char *options, bool probe)
34018c2ecf20Sopenharmony_ci{
34028c2ecf20Sopenharmony_ci	int baud = 9600;
34038c2ecf20Sopenharmony_ci	int bits = 8;
34048c2ecf20Sopenharmony_ci	int parity = 'n';
34058c2ecf20Sopenharmony_ci	int flow = 'n';
34068c2ecf20Sopenharmony_ci	int ret;
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci	if (!port->iobase && !port->membase)
34098c2ecf20Sopenharmony_ci		return -ENODEV;
34108c2ecf20Sopenharmony_ci
34118c2ecf20Sopenharmony_ci	if (options)
34128c2ecf20Sopenharmony_ci		uart_parse_options(options, &baud, &parity, &bits, &flow);
34138c2ecf20Sopenharmony_ci	else if (probe)
34148c2ecf20Sopenharmony_ci		baud = probe_baud(port);
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci	ret = uart_set_options(port, port->cons, baud, parity, bits, flow);
34178c2ecf20Sopenharmony_ci	if (ret)
34188c2ecf20Sopenharmony_ci		return ret;
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_ci	if (port->dev)
34218c2ecf20Sopenharmony_ci		pm_runtime_get_sync(port->dev);
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci	return 0;
34248c2ecf20Sopenharmony_ci}
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ciint serial8250_console_exit(struct uart_port *port)
34278c2ecf20Sopenharmony_ci{
34288c2ecf20Sopenharmony_ci	if (port->dev)
34298c2ecf20Sopenharmony_ci		pm_runtime_put_sync(port->dev);
34308c2ecf20Sopenharmony_ci
34318c2ecf20Sopenharmony_ci	return 0;
34328c2ecf20Sopenharmony_ci}
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci#endif /* CONFIG_SERIAL_8250_CONSOLE */
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3437