Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6909dadd authored by Stephen Boyd's avatar Stephen Boyd Committed by Greg Kroah-Hartman
Browse files

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: default avatarStephen Boyd <sboyd@codeaurora.org>
Acked-by: default avatarDavid Brown <davidb@codeaurora.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f8fb952f
Loading
Loading
Loading
Loading
+44 −54
Original line number Original line Diff line number Diff line
@@ -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);
		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)
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);
	struct msm_port *msm_port = UART_TO_MSM(port);
	const struct msm_baud_map *entry;


	switch (baud) {
	entry = msm_find_best_baud(port, 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;
	}


	if (msm_port->is_uartdm)
	if (msm_port->is_uartdm)
		msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
		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 */
	/* RX stale watermark */
	rxstale = entry->rxstale;
	watermark = UART_IPR_STALE_LSB & rxstale;
	watermark = UART_IPR_STALE_LSB & rxstale;
	watermark |= UART_IPR_RXSTALE_LAST;
	watermark |= UART_IPR_RXSTALE_LAST;
	watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
	watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
+4 −14
Original line number Original line Diff line number Diff line
@@ -39,18 +39,6 @@
#define UART_MR2_PARITY_MODE		0x3
#define UART_MR2_PARITY_MODE		0x3


#define UART_CSR			0x0008
#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_TF		0x000C
#define UART_TF		0x000C
#define UARTDM_TF	0x0070
#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, 0xF1, UART_NREG);
	msm_write(port, 0x0F, UART_DREG);
	msm_write(port, 0x0F, UART_DREG);
	msm_write(port, 0x1A, UART_MNDREG);
	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, 0xF6, UART_NREG);
	msm_write(port, 0x0F, UART_DREG);
	msm_write(port, 0x0F, UART_DREG);
	msm_write(port, 0x0A, UART_MNDREG);
	msm_write(port, 0x0A, UART_MNDREG);
	port->uartclk = 1843200;
}
}


static inline
static inline
@@ -170,7 +160,7 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
{
{
	if (port->uartclk == 19200000)
	if (port->uartclk == 19200000)
		msm_serial_set_mnd_regs_tcxo(port);
		msm_serial_set_mnd_regs_tcxo(port);
	else
	else if (port->uartclk == 4800000)
		msm_serial_set_mnd_regs_tcxoby4(port);
		msm_serial_set_mnd_regs_tcxoby4(port);
}
}