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:
committed by
Greg Kroah-Hartman
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);
|
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);
|
||||||
|
|||||||
@@ -38,19 +38,7 @@
|
|||||||
#define UART_MR2_PARITY_MODE_SPACE 0x3
|
#define UART_MR2_PARITY_MODE_SPACE 0x3
|
||||||
#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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user