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

msm_serial: Make baud_code detection more dynamic

Currently msm_set_baud_rate() assumes the uart clock rate is
1.8432 MHz. This is not always true, and limits our options to
program the baud rate. Instead of assuming the rate and
hard-coding the baud_code based on it, calculate the divider that
we want and try to find the closest baud_code that matches. This
allows us to support uarts with faster clock speeds.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: David Brown <davidb@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Stephen Boyd and committed by
Greg Kroah-Hartman
6909dadd f8fb952f

+48 -68
+44 -54
drivers/tty/serial/msm_serial.c
··· 322 322 msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); 323 323 } 324 324 325 + struct msm_baud_map { 326 + u16 divisor; 327 + u8 code; 328 + u8 rxstale; 329 + }; 330 + 331 + static const struct msm_baud_map * 332 + msm_find_best_baud(struct uart_port *port, unsigned int baud) 333 + { 334 + unsigned int i, divisor; 335 + const struct msm_baud_map *entry; 336 + static const struct msm_baud_map table[] = { 337 + { 1536, 0x00, 1 }, 338 + { 768, 0x11, 1 }, 339 + { 384, 0x22, 1 }, 340 + { 192, 0x33, 1 }, 341 + { 96, 0x44, 1 }, 342 + { 48, 0x55, 1 }, 343 + { 32, 0x66, 1 }, 344 + { 24, 0x77, 1 }, 345 + { 16, 0x88, 1 }, 346 + { 12, 0x99, 6 }, 347 + { 8, 0xaa, 6 }, 348 + { 6, 0xbb, 6 }, 349 + { 4, 0xcc, 6 }, 350 + { 3, 0xdd, 8 }, 351 + { 2, 0xee, 16 }, 352 + { 1, 0xff, 31 }, 353 + }; 354 + 355 + divisor = uart_get_divisor(port, baud); 356 + 357 + for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++) 358 + if (entry->divisor <= divisor) 359 + break; 360 + 361 + return entry; /* Default to smallest divider */ 362 + } 363 + 325 364 static int msm_set_baud_rate(struct uart_port *port, unsigned int baud) 326 365 { 327 - unsigned int baud_code, rxstale, watermark; 366 + unsigned int rxstale, watermark; 328 367 struct msm_port *msm_port = UART_TO_MSM(port); 368 + const struct msm_baud_map *entry; 329 369 330 - switch (baud) { 331 - case 300: 332 - baud_code = UART_CSR_300; 333 - rxstale = 1; 334 - break; 335 - case 600: 336 - baud_code = UART_CSR_600; 337 - rxstale = 1; 338 - break; 339 - case 1200: 340 - baud_code = UART_CSR_1200; 341 - rxstale = 1; 342 - break; 343 - case 2400: 344 - baud_code = UART_CSR_2400; 345 - rxstale = 1; 346 - break; 347 - case 4800: 348 - baud_code = UART_CSR_4800; 349 - rxstale = 1; 350 - break; 351 - case 9600: 352 - baud_code = UART_CSR_9600; 353 - rxstale = 2; 354 - break; 355 - case 14400: 356 - baud_code = UART_CSR_14400; 357 - rxstale = 3; 358 - break; 359 - case 19200: 360 - baud_code = UART_CSR_19200; 361 - rxstale = 4; 362 - break; 363 - case 28800: 364 - baud_code = UART_CSR_28800; 365 - rxstale = 6; 366 - break; 367 - case 38400: 368 - baud_code = UART_CSR_38400; 369 - rxstale = 8; 370 - break; 371 - case 57600: 372 - baud_code = UART_CSR_57600; 373 - rxstale = 16; 374 - break; 375 - case 115200: 376 - default: 377 - baud_code = UART_CSR_115200; 378 - baud = 115200; 379 - rxstale = 31; 380 - break; 381 - } 370 + entry = msm_find_best_baud(port, baud); 382 371 383 372 if (msm_port->is_uartdm) 384 373 msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); 385 374 386 - msm_write(port, baud_code, UART_CSR); 375 + msm_write(port, entry->code, UART_CSR); 387 376 388 377 /* RX stale watermark */ 378 + rxstale = entry->rxstale; 389 379 watermark = UART_IPR_STALE_LSB & rxstale; 390 380 watermark |= UART_IPR_RXSTALE_LAST; 391 381 watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
+4 -14
drivers/tty/serial/msm_serial.h
··· 38 38 #define UART_MR2_PARITY_MODE_SPACE 0x3 39 39 #define UART_MR2_PARITY_MODE 0x3 40 40 41 - #define UART_CSR 0x0008 42 - #define UART_CSR_115200 0xFF 43 - #define UART_CSR_57600 0xEE 44 - #define UART_CSR_38400 0xDD 45 - #define UART_CSR_28800 0xCC 46 - #define UART_CSR_19200 0xBB 47 - #define UART_CSR_14400 0xAA 48 - #define UART_CSR_9600 0x99 49 - #define UART_CSR_4800 0x77 50 - #define UART_CSR_2400 0x55 51 - #define UART_CSR_1200 0x44 52 - #define UART_CSR_600 0x33 53 - #define UART_CSR_300 0x22 41 + #define UART_CSR 0x0008 54 42 55 43 #define UART_TF 0x000C 56 44 #define UARTDM_TF 0x0070 ··· 140 152 msm_write(port, 0xF1, UART_NREG); 141 153 msm_write(port, 0x0F, UART_DREG); 142 154 msm_write(port, 0x1A, UART_MNDREG); 155 + port->uartclk = 1843200; 143 156 } 144 157 145 158 /* ··· 152 163 msm_write(port, 0xF6, UART_NREG); 153 164 msm_write(port, 0x0F, UART_DREG); 154 165 msm_write(port, 0x0A, UART_MNDREG); 166 + port->uartclk = 1843200; 155 167 } 156 168 157 169 static inline ··· 160 170 { 161 171 if (port->uartclk == 19200000) 162 172 msm_serial_set_mnd_regs_tcxo(port); 163 - else 173 + else if (port->uartclk == 4800000) 164 174 msm_serial_set_mnd_regs_tcxoby4(port); 165 175 } 166 176