mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
tty: serial: qcom-geni-serial: Remove uart frequency table. Instead, find suitable frequency with call to clk_round_rate.
Replace the UART frequency table 'root_freq[]' with logic around clk_round_rate() so that SoC details like the available clk frequencies can change and this driver still works. This reduces tight coupling between this UART driver and the SoC clk driver because we no longer have to update the 'root_freq[]' array for new SoCs. Instead the driver determines the available frequencies at runtime. Signed-off-by: Vijaya Krishna Nivarthi <quic_vnivarth@quicinc.com> Link: https://lore.kernel.org/r/1652697510-30543-1-git-send-email-quic_vnivarth@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4ed26f87c7
commit
c2194bc999
@ -149,12 +149,6 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
|
||||
static void qcom_geni_serial_stop_rx(struct uart_port *uport);
|
||||
static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
|
||||
|
||||
static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
32000000, 48000000, 51200000, 64000000,
|
||||
80000000, 96000000, 100000000,
|
||||
102400000, 112000000, 120000000,
|
||||
128000000};
|
||||
|
||||
#define to_dev_port(ptr, member) \
|
||||
container_of(ptr, struct qcom_geni_serial_port, member)
|
||||
|
||||
@ -946,25 +940,43 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long get_clk_cfg(unsigned long clk_freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(root_freq); i++) {
|
||||
if (!(root_freq[i] % clk_freq))
|
||||
return root_freq[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long get_clk_div_rate(unsigned int baud,
|
||||
static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud,
|
||||
unsigned int sampling_rate, unsigned int *clk_div)
|
||||
{
|
||||
unsigned long ser_clk;
|
||||
unsigned long desired_clk;
|
||||
unsigned long freq, prev;
|
||||
unsigned long div, maxdiv;
|
||||
int64_t mult;
|
||||
|
||||
desired_clk = baud * sampling_rate;
|
||||
ser_clk = get_clk_cfg(desired_clk);
|
||||
if (!desired_clk) {
|
||||
pr_err("%s: Invalid frequency\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
maxdiv = CLK_DIV_MSK >> CLK_DIV_SHFT;
|
||||
prev = 0;
|
||||
|
||||
for (div = 1; div <= maxdiv; div++) {
|
||||
mult = div * desired_clk;
|
||||
if (mult > ULONG_MAX)
|
||||
break;
|
||||
|
||||
freq = clk_round_rate(clk, (unsigned long)mult);
|
||||
if (!(freq % desired_clk)) {
|
||||
ser_clk = freq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prev)
|
||||
ser_clk = freq;
|
||||
else if (prev == freq)
|
||||
break;
|
||||
|
||||
prev = freq;
|
||||
}
|
||||
|
||||
if (!ser_clk) {
|
||||
pr_err("%s: Can't find matching DFS entry for baud %d\n",
|
||||
__func__, baud);
|
||||
@ -972,6 +984,9 @@ static unsigned long get_clk_div_rate(unsigned int baud,
|
||||
}
|
||||
|
||||
*clk_div = ser_clk / desired_clk;
|
||||
if (!(*clk_div))
|
||||
*clk_div = 1;
|
||||
|
||||
return ser_clk;
|
||||
}
|
||||
|
||||
@ -1003,7 +1018,8 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
|
||||
if (ver >= QUP_SE_VERSION_2_5)
|
||||
sampling_rate /= 2;
|
||||
|
||||
clk_rate = get_clk_div_rate(baud, sampling_rate, &clk_div);
|
||||
clk_rate = get_clk_div_rate(port->se.clk, baud,
|
||||
sampling_rate, &clk_div);
|
||||
if (!clk_rate)
|
||||
goto out_restart_rx;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user