All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module
@ 2021-09-29 11:30 LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 1/3] serial:8250:Add basic driver support for MCHP PCI1XXXX UART LakshmiPraveen Kopparthi
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: LakshmiPraveen Kopparthi @ 2021-09-29 11:30 UTC (permalink / raw)
  To: gregkh, jirislaby, andriy.shevchenko, macro, zev, vigneshr,
	linux-serial, linux-kernel
  Cc: UNGLinuxDriver

PCI1XXXX UART is a PCIe to UART module. It has 5 SKUs, each is
differentiated by the device IDs in the PCIe config space. Each
SKU supports a maximum of 4 UART ports(UART0,1,2,3) with fixed 
offests.Based on the sub device ID, the combinations of UART 
ports shall be enumerated.

The UART port is compatible with the standard 16550A, but has some 
modifications.The modifications includes a change in the baud rate
settings,auto control of RTS signal for RS485 feature and an
increase of TX & RX FIFO size to 256 Bytes.Also, it has a capability
to wake up the CPU. 

These patches adds the support to enumerate and exercise all the
combinations of UART ports in all the SKUs.

LakshmiPraveen Kopparthi (3):
  Add basic driver support for MCHP PCI1XXXX UART
  Add RS485 support for MCHP PCI1XXXX UART
  Add non standard baudrate support for MCHP PCI1XXXX UART module

 drivers/tty/serial/8250/8250_pci.c  | 384 ++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_port.c |   8 +
 include/uapi/linux/serial_core.h    |   3 +
 3 files changed, 395 insertions(+)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v1 1/3] serial:8250:Add basic driver support for MCHP PCI1XXXX UART
  2021-09-29 11:30 [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module LakshmiPraveen Kopparthi
@ 2021-09-29 11:30 ` LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 2/3] serial:8250:Add RS485 " LakshmiPraveen Kopparthi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: LakshmiPraveen Kopparthi @ 2021-09-29 11:30 UTC (permalink / raw)
  To: gregkh, jirislaby, andriy.shevchenko, macro, zev, vigneshr,
	linux-serial, linux-kernel
  Cc: UNGLinuxDriver

This patch adds the support to enumerate the UART ports for all the
combinations and writes the necessary port specific registers to
initialise the UART ports.In addition to that, writes to the module
registers are added in the init and exit callbacks to support the
suspend and resume functionality.

This patch adds the wakeup feature support.Each UART port has three
wakeup sources and this patch handles the suspend and wakeup
sequence.

Signed-off-by: LakshmiPraveen Kopparthi <LakshmiPraveen.Kopparthi@microchip.com>
---
 drivers/tty/serial/8250/8250_pci.c  | 298 ++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_port.c |   8 +
 include/uapi/linux/serial_core.h    |   3 +
 3 files changed, 309 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 93159557a2fb..12a3e0bd50aa 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -58,6 +58,13 @@ struct serial_private {
 
 #define PCI_DEVICE_ID_HPE_PCI_SERIAL	0x37e
 
+#define PCI_VENDOR_ID_MCHP_PCI1XXXX	0x1055
+#define PCI_DEVICE_ID_MCHP_PCI12000	0xA002
+#define PCI_DEVICE_ID_MCHP_PCI11010	0xA012
+#define PCI_DEVICE_ID_MCHP_PCI11101	0xA022
+#define PCI_DEVICE_ID_MCHP_PCI11400	0xA032
+#define PCI_DEVICE_ID_MCHP_PCI11414	0xA042
+
 static const struct pci_device_id pci_use_msi[] = {
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
 			 0xA000, 0x1000) },
@@ -67,6 +74,16 @@ static const struct pci_device_id pci_use_msi[] = {
 			 0xA000, 0x1000) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL,
 			 PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MCHP_PCI1XXXX,
+			PCI_DEVICE_ID_MCHP_PCI12000, PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MCHP_PCI1XXXX,
+			PCI_DEVICE_ID_MCHP_PCI11101, PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MCHP_PCI1XXXX,
+			PCI_DEVICE_ID_MCHP_PCI11010, PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MCHP_PCI1XXXX,
+			PCI_DEVICE_ID_MCHP_PCI11400, PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MCHP_PCI1XXXX,
+			PCI_DEVICE_ID_MCHP_PCI11414, PCI_ANY_ID, PCI_ANY_ID) },
 	{ }
 };
 
@@ -1853,6 +1870,218 @@ pci_moxa_setup(struct serial_private *priv,
 	return setup_port(priv, port, bar, offset, 0);
 }
 
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_4P	0x0001
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P012	0x0002
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P013	0x0003
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P023	0x0004
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P123	0x0005
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P01	0x0006
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P02	0x0007
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P03	0x0008
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P12	0x0009
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P13	0x000A
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P23	0x000B
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P0	0x000C
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P1	0x000D
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P2	0x000E
+#define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P3	0x000F
+
+#define UART_ACTV_REG 0x11
+#define UART_PCI_CTRL_REG 0x80
+#define UART_WAKE_REG 0x8C
+#define UART_WAKE_MASK_REG 0x90
+#define UART_RESET_REG 0x94
+
+static char pci1xxxx_port_suspend(int line)
+{
+	struct uart_8250_port *up = serial8250_get_port(line);
+	struct uart_port *port = &up->port;
+	unsigned long flags;
+	u8 wakeup_mask;
+	char ret = 0;
+
+	if (port->suspended == 0 && port->dev) {
+		wakeup_mask = readb(up->port.membase + UART_WAKE_MASK_REG);
+
+		spin_lock_irqsave(&port->lock, flags);
+		port->mctrl &= ~TIOCM_OUT2;
+		port->ops->set_mctrl(port, port->mctrl);
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		if ((wakeup_mask & 0x01) == 0x00)
+			ret = 0x01;
+		else
+			ret = 0x00;
+	}
+	writeb(0x07, port->membase + UART_WAKE_REG);
+	return ret;
+}
+
+void pci1xxxx_port_resume(int line)
+{
+	struct uart_8250_port *up = serial8250_get_port(line);
+	struct uart_port *port = &up->port;
+	unsigned long flags;
+
+	writeb(0x07, port->membase + UART_WAKE_REG);
+	if (port->suspended == 0) {
+		spin_lock_irqsave(&port->lock, flags);
+		port->mctrl |= TIOCM_OUT2;
+		port->ops->set_mctrl(port, port->mctrl);
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+}
+
+static int mchp_pci1xxxx_init(struct pci_dev *dev)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+	unsigned int data;
+	void __iomem *p;
+	int rc = 0;
+	int i;
+
+	switch (dev->subsystem_device) {
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P0:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P1:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P2:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P3:
+		rc = 1;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P01:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P02:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P03:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P12:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P13:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P23:
+		rc = 2;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P012:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P123:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P013:
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P023:
+		rc = 3;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_4P:
+		rc = 4;
+		break;
+	}
+
+	if (!IS_ERR_OR_NULL(priv)) {
+		for (i = 0; i < priv->nr; i++) {
+			if (priv->line[i] >= 0)
+				pci1xxxx_port_resume(priv->line[i]);
+		}
+	}
+
+	p = pci_ioremap_bar(dev, 0);
+	if (p) {
+		data = readl(p + UART_RESET_REG);
+		writel(data & (~(0x01 << 16)),
+		       p + UART_RESET_REG);
+
+		writeb(0x00, (p + UART_PCI_CTRL_REG));
+
+		iounmap(p);
+	} else {
+		moan_device("remapping of bar 0 memory failed", dev);
+		return -ENOMEM;
+	}
+	return rc;
+}
+
+static void mchp_pci1xxxx_exit(struct pci_dev *dev)
+{
+	struct serial_private *priv = pci_get_drvdata(dev);
+	unsigned int data;
+	void __iomem *p;
+	char wakeup = 0;
+	int i;
+
+	if (!IS_ERR_OR_NULL(priv)) {
+		for (i = 0; i < priv->nr; i++) {
+			if (priv->line[i] >= 0)
+				wakeup |= pci1xxxx_port_suspend(priv->line[i]);
+		}
+	}
+	p = pci_ioremap_bar(dev, 0);
+	if (p) {
+		data = readl(p + UART_RESET_REG);
+		writel(data | (0x01 << 16),
+		       p + UART_RESET_REG);
+
+		if (wakeup & 0x01)
+			writeb(0x01, (p + UART_PCI_CTRL_REG));
+		iounmap(p);
+	} else {
+		moan_device("remapping of bar 0 memory failed", dev);
+	}
+}
+
+static int mchp_pci1xxxx_setup(struct serial_private *priv,
+			       const struct pciserial_board *board,
+			       struct uart_8250_port *port, int idx)
+{
+	unsigned int bar = FL_GET_BASE(board->flags);
+	int first_offset = 0;
+	int offset;
+	int ret;
+
+	switch (priv->dev->subsystem_device) {
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P1:
+		first_offset = 256;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P2:
+		first_offset = 512;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P3:
+		first_offset = 768;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P02:
+		if (idx > 0)
+			idx++;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P03:
+		if (idx > 0)
+			idx += 2;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P12:
+		first_offset = 256;
+		if (idx > 0)
+			idx++;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P13:
+		first_offset = 256;
+		if (idx > 0)
+			idx++;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_2P23:
+		first_offset = 512;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P123:
+		first_offset = 256;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P013:
+		if (idx > 1)
+			idx++;
+		break;
+	case PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_3P023:
+		if (idx > 0)
+			idx++;
+		break;
+	}
+
+	offset = first_offset + idx * board->uart_offset;
+	port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
+	port->port.type = PORT_MCHP16550A;
+	ret = setup_port(priv, port, bar, offset, board->reg_shift);
+	if (ret < 0)
+		return ret;
+
+	writeb(0x07, port->port.membase + UART_WAKE_REG);
+	writeb(0x01, (port->port.membase + UART_ACTV_REG));
+	return 0;
+}
+
 #define PCI_VENDOR_ID_SBSMODULARIO	0x124B
 #define PCI_SUBVENDOR_ID_SBSMODULARIO	0x124B
 #define PCI_DEVICE_ID_OCTPRO		0x0001
@@ -2778,6 +3007,51 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
 		.setup		= pci_fintek_f815xxa_setup,
 		.init		= pci_fintek_f815xxa_init,
 	},
+	{
+		.vendor         = PCI_VENDOR_ID_MCHP_PCI1XXXX,
+		.device         = PCI_DEVICE_ID_MCHP_PCI12000,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = mchp_pci1xxxx_setup,
+		.init		 = mchp_pci1xxxx_init,
+		.exit		 = mchp_pci1xxxx_exit,
+	},
+	{
+		.vendor         = PCI_VENDOR_ID_MCHP_PCI1XXXX,
+		.device         = PCI_DEVICE_ID_MCHP_PCI11010,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = mchp_pci1xxxx_setup,
+		.init		 = mchp_pci1xxxx_init,
+		.exit		 = mchp_pci1xxxx_exit,
+	},
+	{
+		.vendor         = PCI_VENDOR_ID_MCHP_PCI1XXXX,
+		.device         = PCI_DEVICE_ID_MCHP_PCI11101,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = mchp_pci1xxxx_setup,
+		.init		 = mchp_pci1xxxx_init,
+		.exit		 = mchp_pci1xxxx_exit,
+	},
+	{
+		.vendor         = PCI_VENDOR_ID_MCHP_PCI1XXXX,
+		.device         = PCI_DEVICE_ID_MCHP_PCI11400,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = mchp_pci1xxxx_setup,
+		.init		 = mchp_pci1xxxx_init,
+		.exit		 = mchp_pci1xxxx_exit,
+	},
+	{
+		.vendor         = PCI_VENDOR_ID_MCHP_PCI1XXXX,
+		.device         = PCI_DEVICE_ID_MCHP_PCI11414,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.setup          = mchp_pci1xxxx_setup,
+		.init		 = mchp_pci1xxxx_init,
+		.exit		 = mchp_pci1xxxx_exit,
+	},
 
 	/*
 	 * Default "match everything" terminator entry
@@ -2979,6 +3253,7 @@ enum pci_board_num_t {
 	pbn_moxa8250_2p,
 	pbn_moxa8250_4p,
 	pbn_moxa8250_8p,
+	pbn_mchp_pci1xxxx,
 };
 
 /*
@@ -3809,6 +4084,13 @@ static struct pciserial_board pci_boards[] = {
 		.base_baud      = 921600,
 		.uart_offset	= 0x200,
 	},
+	[pbn_mchp_pci1xxxx] = {
+		.flags		= FL_BASE0,
+		.num_ports      = 1,
+		.base_baud      = 3000000,
+		.uart_offset	= 256,
+		.first_offset	= 0,
+	},
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -5698,6 +5980,22 @@ static const struct pci_device_id serial_pci_tbl[] = {
 	/* Amazon PCI serial device */
 	{ PCI_DEVICE(0x1d0f, 0x8250), .driver_data = pbn_b0_1_115200 },
 
+	/* Microchip PCI to serial interface */
+	{PCI_VENDOR_ID_MCHP_PCI1XXXX, PCI_DEVICE_ID_MCHP_PCI11010,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_mchp_pci1xxxx },
+	{PCI_VENDOR_ID_MCHP_PCI1XXXX, PCI_DEVICE_ID_MCHP_PCI11101,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_mchp_pci1xxxx },
+	{PCI_VENDOR_ID_MCHP_PCI1XXXX, PCI_DEVICE_ID_MCHP_PCI11400,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_mchp_pci1xxxx },
+	{PCI_VENDOR_ID_MCHP_PCI1XXXX, PCI_DEVICE_ID_MCHP_PCI11414,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_mchp_pci1xxxx },
+	{PCI_VENDOR_ID_MCHP_PCI1XXXX, PCI_DEVICE_ID_MCHP_PCI12000,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0, 0, pbn_mchp_pci1xxxx },
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 66374704747e..6a7936f52d9a 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -307,6 +307,14 @@ static const struct serial8250_config uart_config[] = {
 		.rxtrig_bytes	= {1, 32, 64, 112},
 		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP,
 	},
+	[PORT_MCHP16550A] = {
+		.name		= "MCHP16550A",
+		.fifo_size	= 256,
+		.tx_loadsz	= 256,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
+		.rxtrig_bytes	= {2, 66, 130, 194},
+		.flags		= UART_CAP_FIFO,
+	},
 };
 
 /* Uart divisor latch read */
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index c4042dcfdc0c..21f73b42c46f 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -274,4 +274,7 @@
 /* Freescale LINFlexD UART */
 #define PORT_LINFLEXUART	122
 
+/* MCHP 16550A UART with 256 byte FIFOs */
+#define PORT_MCHP16550A 123
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v1 2/3] serial:8250:Add RS485 support for MCHP PCI1XXXX UART
  2021-09-29 11:30 [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 1/3] serial:8250:Add basic driver support for MCHP PCI1XXXX UART LakshmiPraveen Kopparthi
@ 2021-09-29 11:30 ` LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 3/3] serial:8250: Add non standard baudrate " LakshmiPraveen Kopparthi
  2021-09-29 16:48 ` [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module Andy Shevchenko
  3 siblings, 0 replies; 7+ messages in thread
From: LakshmiPraveen Kopparthi @ 2021-09-29 11:30 UTC (permalink / raw)
  To: gregkh, jirislaby, andriy.shevchenko, macro, zev, vigneshr,
	linux-serial, linux-kernel
  Cc: UNGLinuxDriver

UART module has built in support to control the RTS line. This patch 
adds the support to configure the HW control of RTS.

Signed-off-by: LakshmiPraveen Kopparthi <LakshmiPraveen.Kopparthi@microchip.com>
---
 drivers/tty/serial/8250/8250_pci.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 12a3e0bd50aa..b06374fc6212 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1887,11 +1887,39 @@ pci_moxa_setup(struct serial_private *priv,
 #define PCI_SUBDEVICE_ID_MCHP_PCI1XXXX_1P3	0x000F
 
 #define UART_ACTV_REG 0x11
+#define ADC_CFG_REG 0x40
 #define UART_PCI_CTRL_REG 0x80
 #define UART_WAKE_REG 0x8C
 #define UART_WAKE_MASK_REG 0x90
 #define UART_RESET_REG 0x94
 
+#define ADC_EN BIT(0)
+#define ADC_PIN_SEL BIT(1)
+#define ADC_POLARITY BIT(2)
+
+static int mchp_pci1xxxx_rs485_config(struct uart_port *port,
+				      struct serial_rs485 *rs485)
+{
+	u8 data = 0;
+
+	memset(rs485->padding, 0, sizeof(rs485->padding));
+	rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
+
+	if (rs485->flags & SER_RS485_ENABLED) {
+		data = ADC_EN | ADC_PIN_SEL;
+		if (!(rs485->flags & SER_RS485_RTS_ON_SEND)) {
+			data |= ADC_POLARITY;
+			rs485->flags |=  SER_RS485_RTS_AFTER_SEND;
+		}
+	}
+
+	rs485->delay_rts_after_send = 0;
+	rs485->delay_rts_before_send = 0;
+	writeb(data, (port->membase + ADC_CFG_REG));
+	port->rs485 = *rs485;
+	return 0;
+}
+
 static char pci1xxxx_port_suspend(int line)
 {
 	struct uart_8250_port *up = serial8250_get_port(line);
@@ -2073,6 +2101,7 @@ static int mchp_pci1xxxx_setup(struct serial_private *priv,
 	offset = first_offset + idx * board->uart_offset;
 	port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
 	port->port.type = PORT_MCHP16550A;
+	port->port.rs485_config = mchp_pci1xxxx_rs485_config;
 	ret = setup_port(priv, port, bar, offset, board->reg_shift);
 	if (ret < 0)
 		return ret;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v1 3/3] serial:8250: Add non standard baudrate support for MCHP PCI1XXXX UART
  2021-09-29 11:30 [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 1/3] serial:8250:Add basic driver support for MCHP PCI1XXXX UART LakshmiPraveen Kopparthi
  2021-09-29 11:30 ` [PATCH v1 2/3] serial:8250:Add RS485 " LakshmiPraveen Kopparthi
@ 2021-09-29 11:30 ` LakshmiPraveen Kopparthi
  2021-09-29 16:48 ` [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module Andy Shevchenko
  3 siblings, 0 replies; 7+ messages in thread
From: LakshmiPraveen Kopparthi @ 2021-09-29 11:30 UTC (permalink / raw)
  To: gregkh, jirislaby, andriy.shevchenko, macro, zev, vigneshr,
	linux-serial, linux-kernel
  Cc: UNGLinuxDriver

This patch adds support to exercise all the baud rates.Only few
standard baud rates can be achieved by writing the standard
baud rate registers(DLL, DLM).To achieve  all the baud rates,
additional register writes are needed.

Signed-off-by: LakshmiPraveen Kopparthi <LakshmiPraveen.Kopparthi@microchip.com>
---
 drivers/tty/serial/8250/8250_pci.c | 57 ++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index b06374fc6212..cacb8b03f5db 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1888,6 +1888,8 @@ pci_moxa_setup(struct serial_private *priv,
 
 #define UART_ACTV_REG 0x11
 #define ADC_CFG_REG 0x40
+#define CLK_SEL_REG 0x50
+#define CLK_DIVISOR_REG 0x54
 #define UART_PCI_CTRL_REG 0x80
 #define UART_WAKE_REG 0x8C
 #define UART_WAKE_MASK_REG 0x90
@@ -1896,6 +1898,11 @@ pci_moxa_setup(struct serial_private *priv,
 #define ADC_EN BIT(0)
 #define ADC_PIN_SEL BIT(1)
 #define ADC_POLARITY BIT(2)
+#define UART_BIT_SAMPLE_CNT 16
+
+#define CLK_SEL_MASK 0x03
+#define CLK_SEL_500MHZ 0x01
+#define CLK_SEL_166MHZ 0x02
 
 static int mchp_pci1xxxx_rs485_config(struct uart_port *port,
 				      struct serial_rs485 *rs485)
@@ -1920,6 +1927,55 @@ static int mchp_pci1xxxx_rs485_config(struct uart_port *port,
 	return 0;
 }
 
+static void mchp_pci1xxxx_set_termios(struct uart_port *port,
+				      struct ktermios *termios,
+				      struct ktermios *old)
+{
+	unsigned int standard_baud_list[] = {50, 75, 110, 134, 150, 300,
+				600, 1200, 1800, 2000, 2400, 3600,
+				4800, 7200, 9600, 19200, 38400, 57600,
+				115200, 125000, 136400, 150000, 166700,
+				187500, 214300, 250000, 300000, 375000,
+				500000, 750000, 1000000, 1500000};
+	unsigned int baud = tty_termios_baud_rate(termios);
+	unsigned int quot;
+	unsigned int frac;
+	unsigned int i;
+	unsigned int baud_clock;
+
+	baud = tty_termios_baud_rate(termios);
+	serial8250_do_set_termios(port, termios, NULL);
+
+	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
+		writel((port->custom_divisor & 0x3FFFFFFF),
+		       (port->membase + CLK_DIVISOR_REG));
+	} else {
+		for (i = 0; i < ARRAY_SIZE(standard_baud_list); i++) {
+			if (baud == standard_baud_list[i])
+				return;
+		}
+		tty_termios_encode_baud_rate(termios, baud, baud);
+		baud_clock = readb(port->membase + CLK_SEL_REG);
+
+		if ((baud_clock & CLK_SEL_MASK) == CLK_SEL_500MHZ) {
+			quot = 500000000 / (16 * baud);
+			writel(quot, (port->membase + CLK_DIVISOR_REG));
+		} else if ((baud_clock & CLK_SEL_MASK) == CLK_SEL_166MHZ) {
+			quot = (166667 * 1000) / (16 * baud);
+			writel(quot, (port->membase + CLK_DIVISOR_REG));
+		} else {
+			baud = uart_get_baud_rate(port, termios, old,
+						  50, 1500000);
+			quot = ((1000000000) / (baud * UART_BIT_SAMPLE_CNT));
+			frac = (((1000000000 - (quot * baud *
+				UART_BIT_SAMPLE_CNT)) / UART_BIT_SAMPLE_CNT)
+				* 255) / baud;
+			writel(frac | (quot << 8),
+			       (port->membase + CLK_DIVISOR_REG));
+		}
+	}
+}
+
 static char pci1xxxx_port_suspend(int line)
 {
 	struct uart_8250_port *up = serial8250_get_port(line);
@@ -2102,6 +2158,7 @@ static int mchp_pci1xxxx_setup(struct serial_private *priv,
 	port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
 	port->port.type = PORT_MCHP16550A;
 	port->port.rs485_config = mchp_pci1xxxx_rs485_config;
+	port->port.set_termios = mchp_pci1xxxx_set_termios;
 	ret = setup_port(priv, port, bar, offset, board->reg_shift);
 	if (ret < 0)
 		return ret;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module
  2021-09-29 11:30 [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module LakshmiPraveen Kopparthi
                   ` (2 preceding siblings ...)
  2021-09-29 11:30 ` [PATCH v1 3/3] serial:8250: Add non standard baudrate " LakshmiPraveen Kopparthi
@ 2021-09-29 16:48 ` Andy Shevchenko
  2021-10-05  8:48   ` LakshmiPraveen Kopparthi
  3 siblings, 1 reply; 7+ messages in thread
From: Andy Shevchenko @ 2021-09-29 16:48 UTC (permalink / raw)
  To: LakshmiPraveen Kopparthi
  Cc: gregkh, jirislaby, macro, zev, vigneshr, linux-serial,
	linux-kernel, UNGLinuxDriver

On Wed, Sep 29, 2021 at 05:00:46PM +0530, LakshmiPraveen Kopparthi wrote:
> PCI1XXXX UART is a PCIe to UART module. It has 5 SKUs, each is
> differentiated by the device IDs in the PCIe config space. Each
> SKU supports a maximum of 4 UART ports(UART0,1,2,3) with fixed 
> offests.Based on the sub device ID, the combinations of UART 
> ports shall be enumerated.
> 
> The UART port is compatible with the standard 16550A, but has some 
> modifications.The modifications includes a change in the baud rate
> settings,auto control of RTS signal for RS485 feature and an
> increase of TX & RX FIFO size to 256 Bytes.Also, it has a capability
> to wake up the CPU. 
> 
> These patches adds the support to enumerate and exercise all the
> combinations of UART ports in all the SKUs.

>  drivers/tty/serial/8250/8250_pci.c  | 384 ++++++++++++++++++++++++++++

Please, do not add this to 8250_pci.c. Use separate quirk driver as it's done
in plenty of examples:

	8250_lpss.c, 8250_mid.c, 8250_exar.c, ...

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module
  2021-09-29 16:48 ` [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module Andy Shevchenko
@ 2021-10-05  8:48   ` LakshmiPraveen Kopparthi
  2021-10-05  9:47     ` Andy Shevchenko
  0 siblings, 1 reply; 7+ messages in thread
From: LakshmiPraveen Kopparthi @ 2021-10-05  8:48 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: gregkh, jirislaby, macro, zev, vigneshr, linux-serial,
	linux-kernel, UNGLinuxDriver

On Wed, 2021-09-29 at 19:48 +0300, Andy Shevchenko wrote:
> [Some people who received this message don't often get email from
> andriy.shevchenko@linux.intel.com. Learn why this is important at 
> http://aka.ms/LearnAboutSenderIdentification.]
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
> 
> On Wed, Sep 29, 2021 at 05:00:46PM +0530, LakshmiPraveen Kopparthi
> wrote:
> > PCI1XXXX UART is a PCIe to UART module. It has 5 SKUs, each is
> > differentiated by the device IDs in the PCIe config space. Each
> > SKU supports a maximum of 4 UART ports(UART0,1,2,3) with fixed
> > offests.Based on the sub device ID, the combinations of UART
> > ports shall be enumerated.
> > 
> > The UART port is compatible with the standard 16550A, but has some
> > modifications.The modifications includes a change in the baud rate
> > settings,auto control of RTS signal for RS485 feature and an
> > increase of TX & RX FIFO size to 256 Bytes.Also, it has a
> > capability
> > to wake up the CPU.
> > 
> > These patches adds the support to enumerate and exercise all the
> > combinations of UART ports in all the SKUs.
> >  drivers/tty/serial/8250/8250_pci.c  | 384
> > ++++++++++++++++++++++++++++
> 
> Please, do not add this to 8250_pci.c. Use separate quirk driver as
> it's done
> in plenty of examples:
> 
>         8250_lpss.c, 8250_mid.c, 8250_exar.c, ...

Thanks for pointing the examples. I have looked into these examples and
the required functionality can be achieved with a separate driver. But
I would like to know the reason for not adding this to 8250_pci.c. 

> 
> --
> With Best Regards,
> Andy Shevchenko
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module
  2021-10-05  8:48   ` LakshmiPraveen Kopparthi
@ 2021-10-05  9:47     ` Andy Shevchenko
  0 siblings, 0 replies; 7+ messages in thread
From: Andy Shevchenko @ 2021-10-05  9:47 UTC (permalink / raw)
  To: LakshmiPraveen Kopparthi
  Cc: Andy Shevchenko, Greg Kroah-Hartman, Jiri Slaby,
	Maciej W. Rozycki, Zev Weiss, Vignesh R,
	open list:SERIAL DRIVERS, Linux Kernel Mailing List,
	Microchip Linux Driver Support

On Tue, Oct 5, 2021 at 11:49 AM LakshmiPraveen Kopparthi
<LakshmiPraveen.Kopparthi@microchip.com> wrote:
> On Wed, 2021-09-29 at 19:48 +0300, Andy Shevchenko wrote:

...

> > Please, do not add this to 8250_pci.c. Use separate quirk driver as
> > it's done
> > in plenty of examples:
> >
> >         8250_lpss.c, 8250_mid.c, 8250_exar.c, ...
>
> Thanks for pointing the examples. I have looked into these examples and
> the required functionality can be achieved with a separate driver. But
> I would like to know the reason for not adding this to 8250_pci.c.

Maintainability. And we may check, btw, the LOC difference when you
will be ready with a separate driver.
In some cases it would even be a good win.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-10-05  9:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-29 11:30 [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module LakshmiPraveen Kopparthi
2021-09-29 11:30 ` [PATCH v1 1/3] serial:8250:Add basic driver support for MCHP PCI1XXXX UART LakshmiPraveen Kopparthi
2021-09-29 11:30 ` [PATCH v1 2/3] serial:8250:Add RS485 " LakshmiPraveen Kopparthi
2021-09-29 11:30 ` [PATCH v1 3/3] serial:8250: Add non standard baudrate " LakshmiPraveen Kopparthi
2021-09-29 16:48 ` [PATCH v1 0/3] serial:8250:Add driver support for MCHP PCI1XXXX UART module Andy Shevchenko
2021-10-05  8:48   ` LakshmiPraveen Kopparthi
2021-10-05  9:47     ` Andy Shevchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.