1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Synopsys DesignWare 8250 library. */ 3 4 #include <linux/bitops.h> 5 #include <linux/bitfield.h> 6 #include <linux/device.h> 7 #include <linux/kernel.h> 8 #include <linux/property.h> 9 #include <linux/serial_8250.h> 10 #include <linux/serial_core.h> 11 12 #include "8250_dwlib.h" 13 14 /* Offsets for the DesignWare specific registers */ 15 #define DW_UART_TCR 0xac /* Transceiver Control Register (RS485) */ 16 #define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */ 17 #define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */ 18 #define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ 19 #define DW_UART_CPR 0xf4 /* Component Parameter Register */ 20 #define DW_UART_UCV 0xf8 /* UART Component Version */ 21 22 /* Transceiver Control Register bits */ 23 #define DW_UART_TCR_RS485_EN BIT(0) 24 #define DW_UART_TCR_RE_POL BIT(1) 25 #define DW_UART_TCR_DE_POL BIT(2) 26 #define DW_UART_TCR_XFER_MODE GENMASK(4, 3) 27 #define DW_UART_TCR_XFER_MODE_DE_DURING_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 0) 28 #define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1) 29 #define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2) 30 31 /* Component Parameter Register bits */ 32 #define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) 33 #define DW_UART_CPR_AFCE_MODE (1 << 4) 34 #define DW_UART_CPR_THRE_MODE (1 << 5) 35 #define DW_UART_CPR_SIR_MODE (1 << 6) 36 #define DW_UART_CPR_SIR_LP_MODE (1 << 7) 37 #define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) 38 #define DW_UART_CPR_FIFO_ACCESS (1 << 9) 39 #define DW_UART_CPR_FIFO_STAT (1 << 10) 40 #define DW_UART_CPR_SHADOW (1 << 11) 41 #define DW_UART_CPR_ENCODED_PARMS (1 << 12) 42 #define DW_UART_CPR_DMA_EXTRA (1 << 13) 43 #define DW_UART_CPR_FIFO_MODE (0xff << 16) 44 45 /* Helper for FIFO size calculation */ 46 #define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) 47 48 /* 49 * divisor = div(I) + div(F) 50 * "I" means integer, "F" means fractional 51 * quot = div(I) = clk / (16 * baud) 52 * frac = div(F) * 2^dlf_size 53 * 54 * let rem = clk % (16 * baud) 55 * we have: div(F) * (16 * baud) = rem 56 * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) 57 */ 58 static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud, 59 unsigned int *frac) 60 { 61 unsigned int quot, rem, base_baud = baud * 16; 62 struct dw8250_port_data *d = p->private_data; 63 64 quot = p->uartclk / base_baud; 65 rem = p->uartclk % base_baud; 66 *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); 67 68 return quot; 69 } 70 71 static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, 72 unsigned int quot, unsigned int quot_frac) 73 { 74 dw8250_writel_ext(p, DW_UART_DLF, quot_frac); 75 serial8250_do_set_divisor(p, baud, quot, quot_frac); 76 } 77 78 void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) 79 { 80 p->status &= ~UPSTAT_AUTOCTS; 81 if (termios->c_cflag & CRTSCTS) 82 p->status |= UPSTAT_AUTOCTS; 83 84 serial8250_do_set_termios(p, termios, old); 85 } 86 EXPORT_SYMBOL_GPL(dw8250_do_set_termios); 87 88 static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) 89 { 90 u32 tcr; 91 92 tcr = dw8250_readl_ext(p, DW_UART_TCR); 93 tcr &= ~DW_UART_TCR_XFER_MODE; 94 95 if (rs485->flags & SER_RS485_ENABLED) { 96 /* Clear unsupported flags. */ 97 rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | 98 SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND; 99 tcr |= DW_UART_TCR_RS485_EN; 100 101 if (rs485->flags & SER_RS485_RX_DURING_TX) { 102 tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE; 103 } else { 104 /* HW does not support same DE level for tx and rx */ 105 if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == 106 !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) 107 return -EINVAL; 108 109 tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE; 110 } 111 dw8250_writel_ext(p, DW_UART_DE_EN, 1); 112 dw8250_writel_ext(p, DW_UART_RE_EN, 1); 113 } else { 114 rs485->flags = 0; 115 116 tcr &= ~DW_UART_TCR_RS485_EN; 117 } 118 119 /* Reset to default polarity */ 120 tcr |= DW_UART_TCR_DE_POL; 121 tcr &= ~DW_UART_TCR_RE_POL; 122 123 if (!(rs485->flags & SER_RS485_RTS_ON_SEND)) 124 tcr &= ~DW_UART_TCR_DE_POL; 125 if (device_property_read_bool(p->dev, "rs485-rx-active-high")) 126 tcr |= DW_UART_TCR_RE_POL; 127 128 dw8250_writel_ext(p, DW_UART_TCR, tcr); 129 130 rs485->delay_rts_before_send = 0; 131 rs485->delay_rts_after_send = 0; 132 133 p->rs485 = *rs485; 134 135 return 0; 136 } 137 138 /* 139 * Tests if RE_EN register can have non-zero value to see if RS-485 HW support 140 * is present. 141 */ 142 static bool dw8250_detect_rs485_hw(struct uart_port *p) 143 { 144 u32 reg; 145 146 dw8250_writel_ext(p, DW_UART_RE_EN, 1); 147 reg = dw8250_readl_ext(p, DW_UART_RE_EN); 148 dw8250_writel_ext(p, DW_UART_RE_EN, 0); 149 return reg; 150 } 151 152 void dw8250_setup_port(struct uart_port *p) 153 { 154 struct dw8250_port_data *pd = p->private_data; 155 struct dw8250_data *data = to_dw8250_data(pd); 156 struct uart_8250_port *up = up_to_u8250p(p); 157 u32 reg; 158 159 pd->hw_rs485_support = dw8250_detect_rs485_hw(p); 160 if (pd->hw_rs485_support) { 161 p->rs485_config = dw8250_rs485_config; 162 } else { 163 p->rs485_config = serial8250_em485_config; 164 up->rs485_start_tx = serial8250_em485_start_tx; 165 up->rs485_stop_tx = serial8250_em485_stop_tx; 166 } 167 up->capabilities |= UART_CAP_NOTEMT; 168 169 /* 170 * If the Component Version Register returns zero, we know that 171 * ADDITIONAL_FEATURES are not enabled. No need to go any further. 172 */ 173 reg = dw8250_readl_ext(p, DW_UART_UCV); 174 if (!reg) 175 return; 176 177 dev_dbg(p->dev, "Designware UART version %c.%c%c\n", 178 (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); 179 180 dw8250_writel_ext(p, DW_UART_DLF, ~0U); 181 reg = dw8250_readl_ext(p, DW_UART_DLF); 182 dw8250_writel_ext(p, DW_UART_DLF, 0); 183 184 if (reg) { 185 pd->dlf_size = fls(reg); 186 p->get_divisor = dw8250_get_divisor; 187 p->set_divisor = dw8250_set_divisor; 188 } 189 190 reg = dw8250_readl_ext(p, DW_UART_CPR); 191 if (!reg) { 192 reg = data->pdata->cpr_val; 193 dev_dbg(p->dev, "CPR is not available, using 0x%08x instead\n", reg); 194 } 195 if (!reg) 196 return; 197 198 /* Select the type based on FIFO */ 199 if (reg & DW_UART_CPR_FIFO_MODE) { 200 p->type = PORT_16550A; 201 p->flags |= UPF_FIXED_TYPE; 202 p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); 203 up->capabilities = UART_CAP_FIFO | UART_CAP_NOTEMT; 204 } 205 206 if (reg & DW_UART_CPR_AFCE_MODE) 207 up->capabilities |= UART_CAP_AFE; 208 209 if (reg & DW_UART_CPR_SIR_MODE) 210 up->capabilities |= UART_CAP_IRDA; 211 } 212 EXPORT_SYMBOL_GPL(dw8250_setup_port); 213