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>
This commit is contained in:
		
							parent
							
								
									f8fb952fd4
								
							
						
					
					
						commit
						6909dadd91
					
				| @ -322,70 +322,60 @@ static void msm_break_ctl(struct uart_port *port, int break_ctl) | ||||
| 		msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); | ||||
| } | ||||
| 
 | ||||
| struct msm_baud_map { | ||||
| 	u16	divisor; | ||||
| 	u8	code; | ||||
| 	u8	rxstale; | ||||
| }; | ||||
| 
 | ||||
| static const struct msm_baud_map * | ||||
| msm_find_best_baud(struct uart_port *port, unsigned int baud) | ||||
| { | ||||
| 	unsigned int i, divisor; | ||||
| 	const struct msm_baud_map *entry; | ||||
| 	static const struct msm_baud_map table[] = { | ||||
| 		{ 1536, 0x00,  1 }, | ||||
| 		{  768, 0x11,  1 }, | ||||
| 		{  384, 0x22,  1 }, | ||||
| 		{  192, 0x33,  1 }, | ||||
| 		{   96, 0x44,  1 }, | ||||
| 		{   48, 0x55,  1 }, | ||||
| 		{   32, 0x66,  1 }, | ||||
| 		{   24, 0x77,  1 }, | ||||
| 		{   16, 0x88,  1 }, | ||||
| 		{   12, 0x99,  6 }, | ||||
| 		{    8, 0xaa,  6 }, | ||||
| 		{    6, 0xbb,  6 }, | ||||
| 		{    4, 0xcc,  6 }, | ||||
| 		{    3, 0xdd,  8 }, | ||||
| 		{    2, 0xee, 16 }, | ||||
| 		{    1, 0xff, 31 }, | ||||
| 	}; | ||||
| 
 | ||||
| 	divisor = uart_get_divisor(port, baud); | ||||
| 
 | ||||
| 	for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++) | ||||
| 		if (entry->divisor <= divisor) | ||||
| 			break; | ||||
| 
 | ||||
| 	return entry; /* Default to smallest divider */ | ||||
| } | ||||
| 
 | ||||
| static int msm_set_baud_rate(struct uart_port *port, unsigned int baud) | ||||
| { | ||||
| 	unsigned int baud_code, rxstale, watermark; | ||||
| 	unsigned int rxstale, watermark; | ||||
| 	struct msm_port *msm_port = UART_TO_MSM(port); | ||||
| 	const struct msm_baud_map *entry; | ||||
| 
 | ||||
| 	switch (baud) { | ||||
| 	case 300: | ||||
| 		baud_code = UART_CSR_300; | ||||
| 		rxstale = 1; | ||||
| 		break; | ||||
| 	case 600: | ||||
| 		baud_code = UART_CSR_600; | ||||
| 		rxstale = 1; | ||||
| 		break; | ||||
| 	case 1200: | ||||
| 		baud_code = UART_CSR_1200; | ||||
| 		rxstale = 1; | ||||
| 		break; | ||||
| 	case 2400: | ||||
| 		baud_code = UART_CSR_2400; | ||||
| 		rxstale = 1; | ||||
| 		break; | ||||
| 	case 4800: | ||||
| 		baud_code = UART_CSR_4800; | ||||
| 		rxstale = 1; | ||||
| 		break; | ||||
| 	case 9600: | ||||
| 		baud_code = UART_CSR_9600; | ||||
| 		rxstale = 2; | ||||
| 		break; | ||||
| 	case 14400: | ||||
| 		baud_code = UART_CSR_14400; | ||||
| 		rxstale = 3; | ||||
| 		break; | ||||
| 	case 19200: | ||||
| 		baud_code = UART_CSR_19200; | ||||
| 		rxstale = 4; | ||||
| 		break; | ||||
| 	case 28800: | ||||
| 		baud_code = UART_CSR_28800; | ||||
| 		rxstale = 6; | ||||
| 		break; | ||||
| 	case 38400: | ||||
| 		baud_code = UART_CSR_38400; | ||||
| 		rxstale = 8; | ||||
| 		break; | ||||
| 	case 57600: | ||||
| 		baud_code = UART_CSR_57600; | ||||
| 		rxstale = 16; | ||||
| 		break; | ||||
| 	case 115200: | ||||
| 	default: | ||||
| 		baud_code = UART_CSR_115200; | ||||
| 		baud = 115200; | ||||
| 		rxstale = 31; | ||||
| 		break; | ||||
| 	} | ||||
| 	entry = msm_find_best_baud(port, baud); | ||||
| 
 | ||||
| 	if (msm_port->is_uartdm) | ||||
| 		msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); | ||||
| 
 | ||||
| 	msm_write(port, baud_code, UART_CSR); | ||||
| 	msm_write(port, entry->code, UART_CSR); | ||||
| 
 | ||||
| 	/* RX stale watermark */ | ||||
| 	rxstale = entry->rxstale; | ||||
| 	watermark = UART_IPR_STALE_LSB & rxstale; | ||||
| 	watermark |= UART_IPR_RXSTALE_LAST; | ||||
| 	watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2); | ||||
|  | ||||
| @ -38,19 +38,7 @@ | ||||
| #define UART_MR2_PARITY_MODE_SPACE	0x3 | ||||
| #define UART_MR2_PARITY_MODE		0x3 | ||||
| 
 | ||||
| #define UART_CSR	0x0008 | ||||
| #define UART_CSR_115200	0xFF | ||||
| #define UART_CSR_57600	0xEE | ||||
| #define UART_CSR_38400	0xDD | ||||
| #define UART_CSR_28800	0xCC | ||||
| #define UART_CSR_19200	0xBB | ||||
| #define UART_CSR_14400	0xAA | ||||
| #define UART_CSR_9600	0x99 | ||||
| #define UART_CSR_4800	0x77 | ||||
| #define UART_CSR_2400	0x55 | ||||
| #define UART_CSR_1200	0x44 | ||||
| #define UART_CSR_600	0x33 | ||||
| #define UART_CSR_300	0x22 | ||||
| #define UART_CSR			0x0008 | ||||
| 
 | ||||
| #define UART_TF		0x000C | ||||
| #define UARTDM_TF	0x0070 | ||||
| @ -152,6 +140,7 @@ static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) | ||||
| 	msm_write(port, 0xF1, UART_NREG); | ||||
| 	msm_write(port, 0x0F, UART_DREG); | ||||
| 	msm_write(port, 0x1A, UART_MNDREG); | ||||
| 	port->uartclk = 1843200; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -163,6 +152,7 @@ static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) | ||||
| 	msm_write(port, 0xF6, UART_NREG); | ||||
| 	msm_write(port, 0x0F, UART_DREG); | ||||
| 	msm_write(port, 0x0A, UART_MNDREG); | ||||
| 	port->uartclk = 1843200; | ||||
| } | ||||
| 
 | ||||
| static inline | ||||
| @ -170,7 +160,7 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port) | ||||
| { | ||||
| 	if (port->uartclk == 19200000) | ||||
| 		msm_serial_set_mnd_regs_tcxo(port); | ||||
| 	else | ||||
| 	else if (port->uartclk == 4800000) | ||||
| 		msm_serial_set_mnd_regs_tcxoby4(port); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user