^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Freescale LINFlexD UART serial port driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2012-2016 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2017-2019 NXP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* All registers are 32-bit width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define LINCR1 0x0000 /* LIN control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define LINIER 0x0004 /* LIN interrupt enable register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define LINSR 0x0008 /* LIN status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define LINESR 0x000C /* LIN error status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define UARTCR 0x0010 /* UART mode control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define UARTSR 0x0014 /* UART mode status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define LINTCSR 0x0018 /* LIN timeout control status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define LINOCR 0x001C /* LIN output compare register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define LINTOCR 0x0020 /* LIN timeout control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define LINFBRR 0x0024 /* LIN fractional baud rate register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define LINIBRR 0x0028 /* LIN integer baud rate register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define LINCFR 0x002C /* LIN checksum field register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define LINCR2 0x0030 /* LIN control register 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BIDR 0x0034 /* Buffer identifier register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BDRL 0x0038 /* Buffer data register least significant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define BDRM 0x003C /* Buffer data register most significant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define IFER 0x0040 /* Identifier filter enable register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define IFMI 0x0044 /* Identifier filter match index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define IFMR 0x0048 /* Identifier filter mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define GCR 0x004C /* Global control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define UARTPTO 0x0050 /* UART preset timeout register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define UARTCTO 0x0054 /* UART current timeout register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Register field definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define LINFLEXD_LINCR1_INIT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define LINFLEXD_LINCR1_MME BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define LINFLEXD_LINCR1_BF BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define LINFLEXD_LINSR_LINS_INITMODE BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define LINFLEXD_LINSR_LINS_MASK (0xF << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define LINFLEXD_LINIER_SZIE BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define LINFLEXD_LINIER_OCIE BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define LINFLEXD_LINIER_BEIE BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define LINFLEXD_LINIER_CEIE BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define LINFLEXD_LINIER_HEIE BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define LINFLEXD_LINIER_FEIE BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define LINFLEXD_LINIER_BOIE BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define LINFLEXD_LINIER_LSIE BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define LINFLEXD_LINIER_WUIE BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define LINFLEXD_LINIER_DBFIE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define LINFLEXD_LINIER_DBEIETOIE BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define LINFLEXD_LINIER_DRIE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LINFLEXD_LINIER_DTIE BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define LINFLEXD_LINIER_HRIE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LINFLEXD_UARTCR_OSR_MASK (0xF << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define LINFLEXD_UARTCR_OSR(uartcr) (((uartcr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) & LINFLEXD_UARTCR_OSR_MASK) >> 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define LINFLEXD_UARTCR_ROSE BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define LINFLEXD_UARTCR_RFBM BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define LINFLEXD_UARTCR_TFBM BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define LINFLEXD_UARTCR_WL1 BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define LINFLEXD_UARTCR_PC1 BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define LINFLEXD_UARTCR_RXEN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define LINFLEXD_UARTCR_TXEN BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define LINFLEXD_UARTCR_PC0 BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define LINFLEXD_UARTCR_PCE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define LINFLEXD_UARTCR_WL0 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define LINFLEXD_UARTCR_UART BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define LINFLEXD_UARTSR_SZF BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define LINFLEXD_UARTSR_OCF BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define LINFLEXD_UARTSR_PE3 BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define LINFLEXD_UARTSR_PE2 BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define LINFLEXD_UARTSR_PE1 BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define LINFLEXD_UARTSR_PE0 BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define LINFLEXD_UARTSR_RMB BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define LINFLEXD_UARTSR_FEF BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define LINFLEXD_UARTSR_BOF BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define LINFLEXD_UARTSR_RPS BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define LINFLEXD_UARTSR_WUF BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define LINFLEXD_UARTSR_4 BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define LINFLEXD_UARTSR_TO BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define LINFLEXD_UARTSR_DRFRFE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define LINFLEXD_UARTSR_DTFTFF BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define LINFLEXD_UARTSR_NF BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define LINFLEXD_UARTSR_PE (LINFLEXD_UARTSR_PE0 |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) LINFLEXD_UARTSR_PE1 |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) LINFLEXD_UARTSR_PE2 |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) LINFLEXD_UARTSR_PE3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define LINFLEX_LDIV_MULTIPLIER (16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define DRIVER_NAME "fsl-linflexuart"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define DEV_NAME "ttyLF"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define UART_NR 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define EARLYCON_BUFFER_INITIAL_CAP 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define PREINIT_DELAY 2000 /* us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const struct of_device_id linflex_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .compatible = "fsl,s32v234-linflexuart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) MODULE_DEVICE_TABLE(of, linflex_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static struct uart_port *earlycon_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static bool linflex_earlycon_same_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static DEFINE_SPINLOCK(init_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static bool during_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) char *content;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned int len, cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) } earlycon_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void linflex_stop_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned long ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ier = readl(port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ier &= ~(LINFLEXD_LINIER_DTIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) writel(ier, port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void linflex_stop_rx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned long ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ier = readl(port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static inline void linflex_transmit_buffer(struct uart_port *sport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct circ_buf *xmit = &sport->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) while (!uart_circ_empty(xmit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) c = xmit->buf[xmit->tail];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) writeb(c, sport->membase + BDRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* Waiting for data transmission completed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) while (((status = readl(sport->membase + UARTSR)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) LINFLEXD_UARTSR_DTFTFF) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) sport->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) writel(status | LINFLEXD_UARTSR_DTFTFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) uart_write_wakeup(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) linflex_stop_tx(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void linflex_start_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned long ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) linflex_transmit_buffer(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ier = readl(port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) writel(ier | LINFLEXD_LINIER_DTIE, port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static irqreturn_t linflex_txint(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct uart_port *sport = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct circ_buf *xmit = &sport->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_lock_irqsave(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (sport->x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) writeb(sport->x_char, sport->membase + BDRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* waiting for data transmission completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) while (((status = readl(sport->membase + UARTSR)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) LINFLEXD_UARTSR_DTFTFF) != LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) writel(status | LINFLEXD_UARTSR_DTFTFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) linflex_stop_tx(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) linflex_transmit_buffer(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) uart_write_wakeup(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) spin_unlock_irqrestore(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static irqreturn_t linflex_rxint(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct uart_port *sport = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) unsigned int flg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct tty_port *port = &sport->state->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned long flags, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned char rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) bool brk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) spin_lock_irqsave(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) status = readl(sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) while (status & LINFLEXD_UARTSR_RMB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rx = readb(sport->membase + BDRM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) brk = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) flg = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) sport->icount.rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_SZF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) LINFLEXD_UARTSR_FEF | LINFLEXD_UARTSR_PE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (status & LINFLEXD_UARTSR_SZF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) status |= LINFLEXD_UARTSR_SZF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (status & LINFLEXD_UARTSR_BOF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) status |= LINFLEXD_UARTSR_BOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (status & LINFLEXD_UARTSR_FEF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) brk = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) status |= LINFLEXD_UARTSR_FEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (status & LINFLEXD_UARTSR_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) status |= LINFLEXD_UARTSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) writel(status | LINFLEXD_UARTSR_RMB | LINFLEXD_UARTSR_DRFRFE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) status = readl(sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (brk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) uart_handle_break(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (uart_handle_sysrq_char(sport, (unsigned char)rx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) tty_insert_flip_char(port, rx, flg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) spin_unlock_irqrestore(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tty_flip_buffer_push(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static irqreturn_t linflex_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct uart_port *sport = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) status = readl(sport->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (status & LINFLEXD_UARTSR_DRFRFE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) linflex_rxint(irq, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (status & LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) linflex_txint(irq, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* return TIOCSER_TEMT when transmitter is not busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static unsigned int linflex_tx_empty(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) unsigned long status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) status = readl(port->membase + UARTSR) & LINFLEXD_UARTSR_DTFTFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return status ? TIOCSER_TEMT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static unsigned int linflex_get_mctrl(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static void linflex_set_mctrl(struct uart_port *port, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static void linflex_break_ctl(struct uart_port *port, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static void linflex_setup_watermark(struct uart_port *sport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) unsigned long cr, ier, cr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Disable transmission/reception */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ier = readl(sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) writel(ier, sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) cr = readl(sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) cr &= ~(LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) writel(cr, sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Enter initialization mode by setting INIT bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* set the Linflex in master mode and activate by-pass filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cr1 = LINFLEXD_LINCR1_BF | LINFLEXD_LINCR1_MME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) | LINFLEXD_LINCR1_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) writel(cr1, sport->membase + LINCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* wait for init mode entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) while ((readl(sport->membase + LINSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) & LINFLEXD_LINSR_LINS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) != LINFLEXD_LINSR_LINS_INITMODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * UART = 0x1; - Linflex working in UART mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * TXEN = 0x1; - Enable transmission of data now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * RXEn = 0x1; - Receiver enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * WL0 = 0x1; - 8 bit data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * PCE = 0x0; - No parity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* set UART bit to allow writing other bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) writel(LINFLEXD_UARTCR_UART, sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) cr = (LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) LINFLEXD_UARTCR_WL0 | LINFLEXD_UARTCR_UART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) writel(cr, sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) cr1 &= ~(LINFLEXD_LINCR1_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) writel(cr1, sport->membase + LINCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ier = readl(sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ier |= LINFLEXD_LINIER_DRIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) ier |= LINFLEXD_LINIER_DTIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) writel(ier, sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int linflex_startup(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) linflex_setup_watermark(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret = devm_request_irq(port->dev, port->irq, linflex_int, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) DRIVER_NAME, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static void linflex_shutdown(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) unsigned long ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ier = readl(port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) writel(ier, port->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) devm_free_irq(port->dev, port->irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) linflex_set_termios(struct uart_port *port, struct ktermios *termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned long cr, old_cr, cr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) cr = readl(port->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) old_cr = cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* Enter initialization mode by setting INIT bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) cr1 = readl(port->membase + LINCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) cr1 |= LINFLEXD_LINCR1_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) writel(cr1, port->membase + LINCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* wait for init mode entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) while ((readl(port->membase + LINSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) & LINFLEXD_LINSR_LINS_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) != LINFLEXD_LINSR_LINS_INITMODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * only support CS8 and CS7, and for CS7 must enable PE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * supported mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * - (7,e/o,1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * - (8,n,1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * - (8,e/o,1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* enter the UART into configuration mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) while ((termios->c_cflag & CSIZE) != CS8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) (termios->c_cflag & CSIZE) != CS7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) termios->c_cflag &= ~CSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) termios->c_cflag |= old_csize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) old_csize = CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if ((termios->c_cflag & CSIZE) == CS7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Word length: WL1WL0:00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) cr = old_cr & ~LINFLEXD_UARTCR_WL1 & ~LINFLEXD_UARTCR_WL0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if ((termios->c_cflag & CSIZE) == CS8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* Word length: WL1WL0:01 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) cr = (old_cr | LINFLEXD_UARTCR_WL0) & ~LINFLEXD_UARTCR_WL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (termios->c_cflag & CMSPAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if ((termios->c_cflag & CSIZE) != CS8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) termios->c_cflag &= ~CSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) termios->c_cflag |= CS8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* has a space/sticky bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cr |= LINFLEXD_UARTCR_WL0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (termios->c_cflag & CSTOPB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) termios->c_cflag &= ~CSTOPB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* parity must be enabled when CS7 to match 8-bits format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if ((termios->c_cflag & CSIZE) == CS7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) termios->c_cflag |= PARENB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if ((termios->c_cflag & PARENB)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) cr |= LINFLEXD_UARTCR_PCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (termios->c_cflag & PARODD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) cr = (cr | LINFLEXD_UARTCR_PC0) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) (~LINFLEXD_UARTCR_PC1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) cr = cr & (~LINFLEXD_UARTCR_PC1 &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ~LINFLEXD_UARTCR_PC0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) cr &= ~LINFLEXD_UARTCR_PCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) port->read_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (termios->c_iflag & INPCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) port->read_status_mask |= (LINFLEXD_UARTSR_FEF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) LINFLEXD_UARTSR_PE0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) LINFLEXD_UARTSR_PE1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) LINFLEXD_UARTSR_PE2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) LINFLEXD_UARTSR_PE3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) port->read_status_mask |= LINFLEXD_UARTSR_FEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* characters to ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) port->ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) port->ignore_status_mask |= LINFLEXD_UARTSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (termios->c_iflag & IGNBRK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) port->ignore_status_mask |= LINFLEXD_UARTSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * if we're ignoring parity and break indicators,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * ignore overruns too (for real raw support).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) port->ignore_status_mask |= LINFLEXD_UARTSR_BOF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) writel(cr, port->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cr1 &= ~(LINFLEXD_LINCR1_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) writel(cr1, port->membase + LINCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static const char *linflex_type(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return "FSL_LINFLEX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static void linflex_release_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static int linflex_request_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* configure/auto-configure the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void linflex_config_port(struct uart_port *port, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (flags & UART_CONFIG_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) port->type = PORT_LINFLEXUART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static const struct uart_ops linflex_pops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .tx_empty = linflex_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .set_mctrl = linflex_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .get_mctrl = linflex_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .stop_tx = linflex_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .start_tx = linflex_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .stop_rx = linflex_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .break_ctl = linflex_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .startup = linflex_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) .shutdown = linflex_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) .set_termios = linflex_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .type = linflex_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .request_port = linflex_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .release_port = linflex_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .config_port = linflex_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static struct uart_port *linflex_ports[UART_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static void linflex_console_putchar(struct uart_port *port, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) unsigned long cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) cr = readl(port->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) writeb(ch, port->membase + BDRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (!(cr & LINFLEXD_UARTCR_TFBM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) while ((readl(port->membase + UARTSR) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) != LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) while (readl(port->membase + UARTSR) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) LINFLEXD_UARTSR_DTFTFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (!(cr & LINFLEXD_UARTCR_TFBM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) writel((readl(port->membase + UARTSR) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) LINFLEXD_UARTSR_DTFTFF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) port->membase + UARTSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static void linflex_earlycon_putchar(struct uart_port *port, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) char *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!linflex_earlycon_same_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) linflex_console_putchar(port, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) spin_lock_irqsave(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (!during_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) goto outside_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (earlycon_buf.len >= 1 << CONFIG_LOG_BUF_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) goto init_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!earlycon_buf.cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) earlycon_buf.content = kmalloc(EARLYCON_BUFFER_INITIAL_CAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) earlycon_buf.cap = earlycon_buf.content ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) EARLYCON_BUFFER_INITIAL_CAP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) } else if (earlycon_buf.len == earlycon_buf.cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ret = krealloc(earlycon_buf.content, earlycon_buf.cap << 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) earlycon_buf.content = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) earlycon_buf.cap <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (earlycon_buf.len < earlycon_buf.cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) earlycon_buf.content[earlycon_buf.len++] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) goto init_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) outside_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) linflex_console_putchar(port, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) init_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) spin_unlock_irqrestore(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static void linflex_string_write(struct uart_port *sport, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) unsigned long cr, ier = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ier = readl(sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) linflex_stop_tx(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cr = readl(sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) cr |= (LINFLEXD_UARTCR_TXEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) writel(cr, sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) uart_console_write(sport, s, count, linflex_console_putchar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) writel(ier, sport->membase + LINIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) linflex_console_write(struct console *co, const char *s, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct uart_port *sport = linflex_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (sport->sysrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) else if (oops_in_progress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) locked = spin_trylock_irqsave(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) spin_lock_irqsave(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) linflex_string_write(sport, s, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) spin_unlock_irqrestore(&sport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * if the port was already initialised (eg, by a boot loader),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * try to determine the current setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) linflex_console_get_options(struct uart_port *sport, int *parity, int *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) unsigned long cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cr = readl(sport->membase + UARTCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) cr &= LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!cr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* ok, the port was enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (cr & LINFLEXD_UARTCR_PCE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (cr & LINFLEXD_UARTCR_PC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) *parity = 'o';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) *parity = 'e';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if ((cr & LINFLEXD_UARTCR_WL0) && ((cr & LINFLEXD_UARTCR_WL1) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (cr & LINFLEXD_UARTCR_PCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *bits = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) *bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static int __init linflex_console_setup(struct console *co, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) struct uart_port *sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) int baud = 115200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) int bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int flow = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * check whether an invalid uart number has been specified, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * if so, search for the first available port that does have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * console support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (co->index == -1 || co->index >= ARRAY_SIZE(linflex_ports))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) co->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) sport = linflex_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (!sport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) uart_parse_options(options, &baud, &parity, &bits, &flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) linflex_console_get_options(sport, &parity, &bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (earlycon_port && sport->mapbase == earlycon_port->mapbase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) linflex_earlycon_same_instance = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) spin_lock_irqsave(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) during_init = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) spin_unlock_irqrestore(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* Workaround for character loss or output of many invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * characters, when INIT mode is entered shortly after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * character has just been printed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) udelay(PREINIT_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) linflex_setup_watermark(sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ret = uart_set_options(sport, co, baud, parity, bits, flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!linflex_earlycon_same_instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) spin_lock_irqsave(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /* Emptying buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (earlycon_buf.len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) for (i = 0; i < earlycon_buf.len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) linflex_console_putchar(earlycon_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) earlycon_buf.content[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) kfree(earlycon_buf.content);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) earlycon_buf.len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) during_init = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) spin_unlock_irqrestore(&init_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static struct uart_driver linflex_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static struct console linflex_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .name = DEV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .write = linflex_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .device = uart_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .setup = linflex_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) .data = &linflex_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static void linflex_earlycon_write(struct console *con, const char *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unsigned int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct earlycon_device *dev = con->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) uart_console_write(&dev->port, s, n, linflex_earlycon_putchar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) static int __init linflex_early_console_setup(struct earlycon_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) const char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (!device->port.membase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) device->con->write = linflex_earlycon_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) earlycon_port = &device->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) OF_EARLYCON_DECLARE(linflex, "fsl,s32v234-linflexuart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) linflex_early_console_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) #define LINFLEX_CONSOLE (&linflex_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) #define LINFLEX_CONSOLE NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static struct uart_driver linflex_reg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .driver_name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .dev_name = DEV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .nr = ARRAY_SIZE(linflex_ports),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .cons = LINFLEX_CONSOLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int linflex_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct uart_port *sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (!sport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ret = of_alias_get_id(np, "serial");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (ret >= UART_NR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dev_err(&pdev->dev, "driver limited to %d serial ports\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) UART_NR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sport->line = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) sport->mapbase = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) sport->membase = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (IS_ERR(sport->membase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return PTR_ERR(sport->membase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) sport->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) sport->type = PORT_LINFLEXUART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) sport->iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) sport->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) sport->ops = &linflex_pops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) sport->flags = UPF_BOOT_AUTOCONF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) sport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) linflex_ports[sport->line] = sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) platform_set_drvdata(pdev, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ret = uart_add_one_port(&linflex_reg, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int linflex_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct uart_port *sport = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) uart_remove_one_port(&linflex_reg, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static int linflex_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct uart_port *sport = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) uart_suspend_port(&linflex_reg, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int linflex_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct uart_port *sport = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) uart_resume_port(&linflex_reg, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static struct platform_driver linflex_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .probe = linflex_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .remove = linflex_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .of_match_table = linflex_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .pm = &linflex_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static int __init linflex_serial_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ret = uart_register_driver(&linflex_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) ret = platform_driver_register(&linflex_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) uart_unregister_driver(&linflex_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static void __exit linflex_serial_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) platform_driver_unregister(&linflex_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) uart_unregister_driver(&linflex_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) module_init(linflex_serial_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) module_exit(linflex_serial_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) MODULE_DESCRIPTION("Freescale LINFlexD serial port driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) MODULE_LICENSE("GPL v2");