Commit 1ed67ecd authored by Rengarajan S's avatar Rengarajan S Committed by Greg Kroah-Hartman
Browse files

8250: microchip: Add 4 Mbps support in PCI1XXXX UART



The current clock input is set to 62.5 MHz for supporting fractional
divider, which enables generation of an acceptable baud rate from any
frequency. With the current clock input the baud rate range is limited
to 3.9 Mbps. Hence, the current range is extended to support 4 Mbps
with Burst mode operation. Divisor calculation for a given baud rate is
updated as the sampling rate is reduced from 16 to 8 for 4 Mbps.

Signed-off-by: default avatarRengarajan S <rengarajan.s@microchip.com>
Link: https://lore.kernel.org/r/20240125100619.154873-1-rengarajan.s@microchip.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 90d051b6
Loading
Loading
Loading
Loading
+29 −5
Original line number Diff line number Diff line
@@ -82,7 +82,8 @@
#define ADCL_CFG_PIN_SEL			BIT(1)
#define ADCL_CFG_EN				BIT(0)

#define UART_BIT_SAMPLE_CNT			16
#define UART_BIT_SAMPLE_CNT_8			8
#define UART_BIT_SAMPLE_CNT_16			16
#define BAUD_CLOCK_DIV_INT_MSK			GENMASK(31, 8)
#define ADCL_CFG_RTS_DELAY_MASK			GENMASK(11, 8)
#define UART_CLOCK_DEFAULT			(62500 * HZ_PER_KHZ)
@@ -96,6 +97,7 @@
	(UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT)

#define UART_BAUD_CLK_DIVISOR_REG		0x54
#define FRAC_DIV_CFG_REG			0x58

#define UART_RESET_REG				0x94
#define UART_RESET_D3_RESET_DISABLE		BIT(16)
@@ -104,6 +106,10 @@
#define UART_TX_BURST_FIFO			0xA0
#define UART_RX_BURST_FIFO			0xA4

#define UART_BIT_DIVISOR_8			0x26731000
#define UART_BIT_DIVISOR_16			0x6ef71000
#define UART_BAUD_4MBPS				4000000

#define MAX_PORTS				4
#define PORT_OFFSET				0x100
#define RX_BUF_SIZE				512
@@ -210,15 +216,24 @@ static int pci1xxxx_get_num_ports(struct pci_dev *dev)
static unsigned int pci1xxxx_get_divisor(struct uart_port *port,
					 unsigned int baud, unsigned int *frac)
{
	unsigned int uart_sample_cnt;
	unsigned int quot;

	if (baud >= UART_BAUD_4MBPS) {
		uart_sample_cnt = UART_BIT_SAMPLE_CNT_8;
		writel(UART_BIT_DIVISOR_8, (port->membase + FRAC_DIV_CFG_REG));
	} else {
		uart_sample_cnt = UART_BIT_SAMPLE_CNT_16;
		writel(UART_BIT_DIVISOR_16, (port->membase + FRAC_DIV_CFG_REG));
	}

	/*
	 * Calculate baud rate sampling period in nanoseconds.
	 * Fractional part x denotes x/255 parts of a nanosecond.
	 */
	quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT);
	*frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) *
		  255 / UART_BIT_SAMPLE_CNT / baud;
	quot = NSEC_PER_SEC / (baud * uart_sample_cnt);
	*frac = (NSEC_PER_SEC - quot * baud * uart_sample_cnt) *
		  255 / uart_sample_cnt / baud;

	return quot;
}
@@ -237,7 +252,16 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
	u32 delay_in_baud_periods;
	u32 baud_period_in_ns;
	u32 mode_cfg = 0;
	u32 sample_cnt;
	u32 clock_div;
	u32 frac_div;

	frac_div = readl(port->membase + FRAC_DIV_CFG_REG);

	if (frac_div == UART_BIT_DIVISOR_16)
		sample_cnt = UART_BIT_SAMPLE_CNT_16;
	else
		sample_cnt = UART_BIT_SAMPLE_CNT_8;

	/*
	 * pci1xxxx's uart hardware supports only RTS delay after
@@ -253,7 +277,7 @@ static int pci1xxxx_rs485_config(struct uart_port *port,
			clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG);
			baud_period_in_ns =
				FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) *
				UART_BIT_SAMPLE_CNT;
				sample_cnt;
			delay_in_baud_periods =
				rs485->delay_rts_after_send * NSEC_PER_MSEC /
				baud_period_in_ns;
+7 −0
Original line number Diff line number Diff line
@@ -2681,6 +2681,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
					     struct ktermios *termios,
					     const struct ktermios *old)
{
	struct uart_8250_port *up = up_to_u8250p(port);
	unsigned int tolerance = port->uartclk / 100;
	unsigned int min;
	unsigned int max;
@@ -2698,6 +2699,12 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
		max = (port->uartclk + tolerance) / 16;
	}

	/*
	 * Microchip PCI1XXXX UART supports maximum baud rate up to 4 Mbps
	 */
	if (up->port.type == PORT_MCHP16550A)
		max = 4000000;

	/*
	 * Ask the core to calculate the divisor for us.
	 * Allow 1% tolerance at the upper limit so uart clks marginally