[PATCH 1/2] serial: 8250_pci: add Intel Broxton HSUART support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Huiquan Zhong <huiquan.zhong@xxxxxxxxx>

Intel Broxton contain 4 HSUART ports, Support for 16750 compatible
Auto Flow Control with 64 FIFOs.

Signed-off-by: Huiquan Zhong <huiquan.zhong@xxxxxxxxx>
---
 drivers/tty/serial/8250/8250_pci.c | 152 ++++++++++++++++++++++++++++++++-----
 1 file changed, 135 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 892eb32..824ca72 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1387,50 +1387,53 @@ ce4100_serial_setup(struct serial_private *priv,
 #define BYT_TX_OVF_INT			0x820
 #define BYT_TX_OVF_INT_MASK		(1 << 1)
 
-static void
-byt_set_termios(struct uart_port *p, struct ktermios *termios,
-		struct ktermios *old)
+static inline void calc_for_prv_clk_div(struct uart_port *p, unsigned int baud,
+		unsigned int *m, unsigned int *n)
 {
-	unsigned int baud = tty_termios_baud_rate(termios);
-	unsigned int m, n;
-	u32 reg;
-
 	/*
 	 * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
 	 * dividers must be adjusted.
 	 *
 	 * uartclk = (m / n) * 100 MHz, where m <= n
 	 */
+	*n = 100;
 	switch (baud) {
 	case 500000:
 	case 1000000:
 	case 2000000:
 	case 4000000:
-		m = 64;
-		n = 100;
+		*m = 64;
 		p->uartclk = 64000000;
 		break;
 	case 3500000:
-		m = 56;
-		n = 100;
+		*m = 56;
 		p->uartclk = 56000000;
 		break;
 	case 1500000:
 	case 3000000:
-		m = 48;
-		n = 100;
+		*m = 48;
 		p->uartclk = 48000000;
 		break;
 	case 2500000:
-		m = 40;
-		n = 100;
+		*m = 40;
 		p->uartclk = 40000000;
 		break;
 	default:
-		m = 2304;
-		n = 3125;
+		*m = 2304;
+		*n = 3125;
 		p->uartclk = 73728000;
 	}
+}
+
+static void
+byt_set_termios(struct uart_port *p, struct ktermios *termios,
+		struct ktermios *old)
+{
+	unsigned int baud = tty_termios_baud_rate(termios);
+	unsigned int m, n;
+	u32 reg;
+
+	calc_for_prv_clk_div(p, baud, &m, &n);
 
 	/* Reset the clock */
 	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
@@ -1525,6 +1528,71 @@ byt_serial_setup(struct serial_private *priv,
 	return ret;
 }
 
+#define PCI_DEVICE_ID_INTEL_BXT_UART0	0x0abc
+#define PCI_DEVICE_ID_INTEL_BXT_UART1	0x0abe
+#define PCI_DEVICE_ID_INTEL_BXT_UART2	0x0ac0
+#define PCI_DEVICE_ID_INTEL_BXT_UART3	0x0aee
+
+#define BXT_PRV_CLK			0x200
+#define BXT_PRV_CLK_EN			(1 << 0)
+#define BXT_PRV_CLK_M_VAL_SHIFT		1
+#define BXT_PRV_CLK_N_VAL_SHIFT		16
+#define BXT_PRV_CLK_UPDATE		(1 << 31)
+
+#define BXT_UART_RESET			0x204
+#define BXT_UART_IDMA_RESET		(1 << 2)
+#define BXT_UART_HOST_RESET		0x3
+
+#define BXT_UART_IC_CLOCK		0x238
+#define BXT_UART_IC_CLOCK_IDMA		0xc
+#define BXT_UART_IC_CLOCK_UART		0x3
+
+static void
+bxt_set_termios(struct uart_port *p, struct ktermios *termios,
+		struct ktermios *old)
+{
+	unsigned int baud = tty_termios_baud_rate(termios);
+	unsigned int m, n;
+	u32 reg;
+
+	calc_for_prv_clk_div(p, baud, &m, &n);
+
+	/* Reset the clock */
+	reg = (m << BXT_PRV_CLK_M_VAL_SHIFT) | (n << BXT_PRV_CLK_N_VAL_SHIFT);
+	writel(reg, p->membase + BXT_PRV_CLK);
+	reg |= BXT_PRV_CLK_EN | BXT_PRV_CLK_UPDATE;
+	writel(reg, p->membase + BXT_PRV_CLK);
+
+	serial8250_do_set_termios(p, termios, old);
+}
+
+static int
+bxt_serial_setup(struct serial_private *priv,
+		 const struct pciserial_board *board,
+		 struct uart_8250_port *port, int idx)
+{
+	int ret;
+
+	ret = pci_default_setup(priv, board, port, idx);
+	port->port.iotype = UPIO_MEM;
+	port->port.type = PORT_16550A;
+	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	port->port.set_termios = bxt_set_termios;
+	port->port.fifosize = 64;
+	port->tx_loadsz = 64;
+	port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
+
+	/* Hw reset */
+	writel(0, port->port.membase + BXT_UART_RESET);
+	writel(BXT_UART_IDMA_RESET | BXT_UART_HOST_RESET,
+			port->port.membase + BXT_UART_RESET);
+	/* clock not gate */
+	writel(BXT_UART_IC_CLOCK_IDMA | BXT_UART_IC_CLOCK_UART,
+			port->port.membase + BXT_UART_IC_CLOCK);
+
+	return ret;
+}
+
 static int
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
@@ -2001,6 +2069,34 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.setup		= byt_serial_setup,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BXT_UART0,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= bxt_serial_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BXT_UART1,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= bxt_serial_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BXT_UART2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= bxt_serial_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BXT_UART3,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= bxt_serial_setup,
+	},
 	/*
 	 * ITE
 	 */
@@ -2865,6 +2961,7 @@ enum pci_board_num_t {
 	pbn_ce4100_1_115200,
 	pbn_byt,
 	pbn_qrk,
+	pbn_bxt,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
 	pbn_brcm_trumanage,
@@ -3636,6 +3733,12 @@ static struct pciserial_board pci_boards[] = {
 		.base_baud	= 2764800,
 		.reg_shift	= 2,
 	},
+	[pbn_bxt] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 2764800,
+		.reg_shift      = 2,
+	},
 	[pbn_omegapci] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 8,
@@ -5368,6 +5471,21 @@ static struct pci_device_id serial_pci_tbl[] = {
 	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_qrk },
+	/* Intel Broxton */
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_UART0,
+		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+		pbn_bxt },
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_UART1,
+		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+		pbn_bxt },
+
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_UART2,
+		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+		pbn_bxt },
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_UART3,
+		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+		pbn_bxt },
+
 	/*
 	 * Cronyx Omega PCI
 	 */
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux