Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: 8250-mtk: modify baudrate setting

In termios function, add Fractional divider to adjust baudrate.

Signed-off-by: Long Cheng <long.cheng@mediatek.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Long Cheng and committed by
Greg Kroah-Hartman
bdbd0a7f 8ceeb470

+102
+102
drivers/tty/serial/8250/8250_mtk.c
··· 25 25 #define MTK_UART_SAMPLE_COUNT 0x0a /* Sample count register */ 26 26 #define MTK_UART_SAMPLE_POINT 0x0b /* Sample point register */ 27 27 #define MTK_UART_RATE_FIX 0x0d /* UART Rate Fix Register */ 28 + #define MTK_UART_ESCAPE_DAT 0x10 /* Escape Character register */ 29 + #define MTK_UART_ESCAPE_EN 0x11 /* Escape Enable register */ 28 30 #define MTK_UART_DMA_EN 0x13 /* DMA Enable register */ 29 31 #define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */ 30 32 #define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */ 31 33 #define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */ 34 + #define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */ 35 + #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ 36 + #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ 37 + 38 + #define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */ 39 + #define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */ 40 + #define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */ 41 + #define MTK_UART_EFR_NO_SW_FC 0x0 /* no sw flow control */ 42 + #define MTK_UART_EFR_XON1_XOFF1 0xa /* XON1/XOFF1 as sw flow control */ 43 + #define MTK_UART_EFR_XON2_XOFF2 0x5 /* XON2/XOFF2 as sw flow control */ 44 + #define MTK_UART_EFR_SW_FC_MASK 0xf /* Enable CTS Modem status interrupt */ 45 + #define MTK_UART_EFR_HW_FC (MTK_UART_EFR_RTS | MTK_UART_EFR_CTS) 32 46 #define MTK_UART_DMA_EN_TX 0x2 33 47 #define MTK_UART_DMA_EN_RX 0x5 34 48 49 + #define MTK_UART_ESCAPE_CHAR 0x77 /* Escape char added under sw fc */ 35 50 #define MTK_UART_TX_SIZE UART_XMIT_SIZE 36 51 #define MTK_UART_RX_SIZE 0x8000 37 52 #define MTK_UART_TX_TRIGGER 1 ··· 70 55 #ifdef CONFIG_SERIAL_8250_DMA 71 56 enum dma_rx_status rx_status; 72 57 #endif 58 + }; 59 + 60 + /* flow control mode */ 61 + enum { 62 + MTK_UART_FC_NONE, 63 + MTK_UART_FC_SW, 64 + MTK_UART_FC_HW, 73 65 }; 74 66 75 67 #ifdef CONFIG_SERIAL_8250_DMA ··· 217 195 return serial8250_do_shutdown(port); 218 196 } 219 197 198 + static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask) 199 + { 200 + serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask)); 201 + } 202 + 203 + static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask) 204 + { 205 + serial_out(up, UART_IER, serial_in(up, UART_IER) | mask); 206 + } 207 + 208 + static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) 209 + { 210 + struct uart_port *port = &up->port; 211 + int lcr = serial_in(up, UART_LCR); 212 + 213 + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 214 + serial_out(up, UART_EFR, UART_EFR_ECB); 215 + serial_out(up, UART_LCR, lcr); 216 + lcr = serial_in(up, UART_LCR); 217 + 218 + switch (mode) { 219 + case MTK_UART_FC_NONE: 220 + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); 221 + serial_out(up, MTK_UART_ESCAPE_EN, 0x00); 222 + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 223 + serial_out(up, UART_EFR, serial_in(up, UART_EFR) & 224 + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))); 225 + serial_out(up, UART_LCR, lcr); 226 + mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI | 227 + MTK_UART_IER_RTSI | MTK_UART_IER_CTSI); 228 + break; 229 + 230 + case MTK_UART_FC_HW: 231 + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); 232 + serial_out(up, MTK_UART_ESCAPE_EN, 0x00); 233 + serial_out(up, UART_MCR, UART_MCR_RTS); 234 + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 235 + 236 + /*enable hw flow control*/ 237 + serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC | 238 + (serial_in(up, UART_EFR) & 239 + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); 240 + 241 + serial_out(up, UART_LCR, lcr); 242 + mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI); 243 + mtk8250_enable_intrs(up, MTK_UART_IER_CTSI | MTK_UART_IER_RTSI); 244 + break; 245 + 246 + case MTK_UART_FC_SW: /*MTK software flow control */ 247 + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); 248 + serial_out(up, MTK_UART_ESCAPE_EN, 0x01); 249 + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); 250 + 251 + /*enable sw flow control */ 252 + serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 | 253 + (serial_in(up, UART_EFR) & 254 + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); 255 + 256 + serial_out(up, UART_XON1, START_CHAR(port->state->port.tty)); 257 + serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty)); 258 + serial_out(up, UART_LCR, lcr); 259 + mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI); 260 + mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI); 261 + break; 262 + default: 263 + break; 264 + } 265 + } 266 + 220 267 static void 221 268 mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, 222 269 struct ktermios *old) ··· 299 208 struct uart_8250_port *up = up_to_u8250p(port); 300 209 unsigned int baud, quot, fraction; 301 210 unsigned long flags; 211 + int mode; 302 212 303 213 #ifdef CONFIG_SERIAL_8250_DMA 304 214 if (up->dma) { ··· 373 281 serial_port_out(port, MTK_UART_FRACDIV_L, 0x00); 374 282 serial_port_out(port, MTK_UART_FRACDIV_M, 0x00); 375 283 } 284 + 285 + if ((termios->c_cflag & CRTSCTS) && (!(termios->c_iflag & CRTSCTS))) 286 + mode = MTK_UART_FC_HW; 287 + else if (termios->c_iflag & CRTSCTS) 288 + mode = MTK_UART_FC_SW; 289 + else 290 + mode = MTK_UART_FC_NONE; 291 + 292 + mtk8250_set_flow_ctrl(up, mode); 293 + 376 294 if (uart_console(port)) 377 295 up->port.cons->cflag = termios->c_cflag; 378 296