All of lore.kernel.org
 help / color / mirror / Atom feed
From: matthew.gerlach@linux.intel.com
To: hao.wu@intel.com, yilun.xu@intel.com, russell.h.weight@intel.com,
	basheer.ahmed.muddebihal@intel.com, trix@redhat.com,
	mdf@kernel.org, linux-fpga@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	tianfei.zhang@intel.com, corbet@lwn.net,
	gregkh@linuxfoundation.org, linux-serial@vger.kernel.org,
	jirislaby@kernel.org, geert+renesas@glider.be,
	andriy.shevchenko@linux.intel.com,
	niklas.soderlund+renesas@ragnatech.se, phil.edworthy@renesas.com,
	macro@orcam.me.uk, johan@kernel.org, lukas@wunner.de
Cc: Matthew Gerlach <matthew.gerlach@linux.intel.com>
Subject: [PATCH v1 5/5] tty: serial: 8250: add DFL bus driver for Altera 16550.
Date: Tue,  6 Sep 2022 12:04:26 -0700	[thread overview]
Message-ID: <20220906190426.3139760-6-matthew.gerlach@linux.intel.com> (raw)
In-Reply-To: <20220906190426.3139760-1-matthew.gerlach@linux.intel.com>

From: Matthew Gerlach <matthew.gerlach@linux.intel.com>

Add a Device Feature List (DFL) bus driver for the Altera
16550 implementation of UART.

Signed-off-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dfl.c | 188 +++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |   9 ++
 drivers/tty/serial/8250/Makefile   |   1 +
 include/linux/dfl.h                |   7 ++
 4 files changed, 205 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_dfl.c

diff --git a/drivers/tty/serial/8250/8250_dfl.c b/drivers/tty/serial/8250/8250_dfl.c
new file mode 100644
index 000000000000..dcf6638a298c
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_dfl.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for FPGA UART
+ *
+ * Copyright (C) 2022 Intel Corporation, Inc.
+ *
+ * Authors:
+ *   Ananda Ravuri <ananda.ravuri@intel.com>
+ *   Matthew Gerlach <matthew.gerlach@linux.intel.com>
+ */
+
+#include <linux/dfl.h>
+#include <linux/version.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bitfield.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
+struct dfl_uart {
+	void __iomem   *csr_base;
+	u64             csr_addr;
+	unsigned int    csr_size;
+	struct device  *dev;
+	u64             uart_clk;
+	u64             fifo_len;
+	unsigned int    fifo_size;
+	unsigned int    reg_shift;
+	unsigned int    line;
+};
+
+int feature_uart_walk(struct dfl_uart *dfluart, resource_size_t max)
+{
+	void __iomem *param_base;
+	int off;
+	u64 v;
+
+	v = readq(dfluart->csr_base + DFHv1_CSR_ADDR);
+	dfluart->csr_addr = FIELD_GET(DFHv1_CSR_ADDR_MASK, v);
+
+	v = readq(dfluart->csr_base + DFHv1_CSR_SIZE_GRP);
+	dfluart->csr_size = FIELD_GET(DFHv1_CSR_SIZE_GRP_SIZE, v);
+
+	if (dfluart->csr_addr == 0 || dfluart->csr_size == 0) {
+		dev_err(dfluart->dev, "FIXME bad dfh address and size\n");
+		return -EINVAL;
+	}
+
+	if (!FIELD_GET(DFHv1_CSR_SIZE_GRP_HAS_PARAMS, v)) {
+		dev_err(dfluart->dev, "missing required parameters\n");
+		return -EINVAL;
+	}
+
+	param_base = dfluart->csr_base + DFHv1_PARAM_HDR;
+
+	off = dfl_find_param(param_base, max, DFHv1_PARAM_ID_CLK_FRQ);
+	if (off < 0) {
+		dev_err(dfluart->dev, "missing CLK_FRQ param\n");
+		return -EINVAL;
+	}
+
+	dfluart->uart_clk = readq(param_base + off + DFHv1_PARAM_DATA);
+	dev_dbg(dfluart->dev, "UART_CLK_ID %llu Hz\n", dfluart->uart_clk);
+
+	off = dfl_find_param(param_base, max, DFHv1_PARAM_ID_FIFO_LEN);
+	if (off < 0) {
+		dev_err(dfluart->dev, "missing FIFO_LEN param\n");
+		return -EINVAL;
+	}
+
+	dfluart->fifo_len = readq(param_base + off + DFHv1_PARAM_DATA);
+	dev_dbg(dfluart->dev, "UART_FIFO_ID fifo_len %llu\n", dfluart->fifo_len);
+
+	off = dfl_find_param(param_base, max, DFHv1_PARAM_ID_REG_LAYOUT);
+	if (off < 0) {
+		dev_err(dfluart->dev, "missing REG_LAYOUT param\n");
+		return -EINVAL;
+	}
+
+	v = readq(param_base + off + DFHv1_PARAM_DATA);
+	dfluart->fifo_size = FIELD_GET(DFHv1_PARAM_ID_REG_WIDTH, v);
+	dfluart->reg_shift = FIELD_GET(DFHv1_PARAM_ID_REG_SHIFT, v);
+	dev_dbg(dfluart->dev, "UART_LAYOUT_ID width %d shift %d\n",
+		dfluart->fifo_size, dfluart->reg_shift);
+
+	return 0;
+}
+
+static int dfl_uart_probe(struct dfl_device *dfl_dev)
+{
+	struct device *dev = &dfl_dev->dev;
+	struct uart_8250_port uart;
+	struct dfl_uart *dfluart;
+	int ret;
+
+	memset(&uart, 0, sizeof(uart));
+
+	dfluart = devm_kzalloc(dev, sizeof(*dfluart), GFP_KERNEL);
+	if (!dfluart)
+		return -ENOMEM;
+
+	dfluart->csr_base = devm_ioremap_resource(dev, &dfl_dev->mmio_res);
+	if (IS_ERR(dfluart->csr_base)) {
+		dev_err(dev, "failed to get mem resource!\n");
+		return PTR_ERR(dfluart->csr_base);
+	}
+
+	dfluart->dev = dev;
+
+	ret = feature_uart_walk(dfluart, resource_size(&dfl_dev->mmio_res));
+	if (ret < 0) {
+		dev_err(dev, "failed to uart feature walk %d\n", ret);
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "nr_irqs %d %p\n", dfl_dev->num_irqs, dfl_dev->irqs);
+
+	if (dfl_dev->num_irqs == 1)
+		uart.port.irq = dfl_dev->irqs[0];
+
+	switch (dfluart->fifo_len) {
+	case 32:
+		uart.port.type = PORT_ALTR_16550_F32;
+		break;
+
+	case 64:
+		uart.port.type = PORT_ALTR_16550_F64;
+		break;
+
+	case 128:
+		uart.port.type = PORT_ALTR_16550_F128;
+		break;
+
+	default:
+		dev_err(dev, "bad fifo_len %llu\n", dfluart->fifo_len);
+		return -EINVAL;
+	}
+
+	uart.port.iotype = UPIO_MEM32;
+	uart.port.membase = dfluart->csr_base + dfluart->csr_addr;
+	uart.port.mapsize = dfluart->csr_size;
+	uart.port.regshift = dfluart->reg_shift;
+	uart.port.uartclk = dfluart->uart_clk;
+
+	/* register the port */
+	ret = serial8250_register_8250_port(&uart);
+	if (ret < 0) {
+		dev_err(dev, "unable to register 8250 port %d.\n", ret);
+		return -EINVAL;
+	}
+	dev_info(dev, "serial8250_register_8250_port %d\n", ret);
+	dfluart->line = ret;
+	dev_set_drvdata(dev, dfluart);
+
+	return 0;
+}
+
+static void dfl_uart_remove(struct dfl_device *dfl_dev)
+{
+	struct dfl_uart *dfluart = dev_get_drvdata(&dfl_dev->dev);
+
+	if (dfluart->line > 0)
+		serial8250_unregister_port(dfluart->line);
+}
+
+#define FME_FEATURE_ID_UART 0x24
+
+static const struct dfl_device_id dfl_uart_ids[] = {
+	{ FME_ID, FME_FEATURE_ID_UART },
+	{ }
+};
+
+static struct dfl_driver dfl_uart_driver = {
+	.drv = {
+		.name = "dfl-uart",
+	},
+	.id_table = dfl_uart_ids,
+	.probe = dfl_uart_probe,
+	.remove = dfl_uart_remove,
+};
+
+module_dfl_driver(dfl_uart_driver);
+
+MODULE_DEVICE_TABLE(dfl, dfl_uart_ids);
+MODULE_DESCRIPTION("DFL Intel UART driver");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index d0b49e15fbf5..fbb59216ce7f 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -546,3 +546,12 @@ config SERIAL_OF_PLATFORM
 	  are probed through devicetree, including Open Firmware based
 	  PowerPC systems and embedded systems on architectures using the
 	  flattened device tree format.
+
+config SERIAL_8250_DFL
+	tristate "DFL bus driver for Altera 16550 UART"
+	depends on SERIAL_8250 && FPGA_DFL
+	help
+	  This option enables support for a Device Feature List (DFL) bus
+	  driver for the Altera 16650 UART.  One or more Altera 16650 UARTs
+	  can be instantiated in a FPGA and then be discovered during
+	  enumeration of the DFL bus.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index bee908f99ea0..8e987b04820a 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -43,5 +43,6 @@ obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 obj-$(CONFIG_SERIAL_8250_TEGRA)		+= 8250_tegra.o
 obj-$(CONFIG_SERIAL_8250_BCM7271)	+= 8250_bcm7271.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o
+obj-$(CONFIG_SERIAL_8250_DFL)		+= 8250_dfl.o
 
 CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/include/linux/dfl.h b/include/linux/dfl.h
index 5652879ab48e..d37636090fed 100644
--- a/include/linux/dfl.h
+++ b/include/linux/dfl.h
@@ -73,6 +73,13 @@
 #define DFHv1_PARAM_MSIX_STARTV	0x8
 #define DFHv1_PARAM_MSIX_NUMV	0xc
 
+#define DFHv1_PARAM_ID_CLK_FRQ    0x2
+#define DFHv1_PARAM_ID_FIFO_LEN   0x3
+
+#define DFHv1_PARAM_ID_REG_LAYOUT 0x4
+#define DFHv1_PARAM_ID_REG_WIDTH  GENMASK_ULL(63, 32)
+#define DFHv1_PARAM_ID_REG_SHIFT  GENMASK_ULL(31, 0)
+
 /**
  * enum dfl_id_type - define the DFL FIU types
  */
-- 
2.25.1


  parent reply	other threads:[~2022-09-06 19:04 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-06 19:04 [PATCH v1 0/5] Enhance definition of DFH and use enhancements for uart driver matthew.gerlach
2022-09-06 19:04 ` [PATCH v1 1/5] Documentation: fpga: dfl: Add documentation for DFHv1 matthew.gerlach
2022-09-06 20:08   ` Andy Shevchenko
2022-09-07 19:15     ` matthew.gerlach
2022-09-11  9:57   ` Xu Yilun
2022-09-11 16:06     ` matthew.gerlach
2022-09-06 19:04 ` [PATCH v1 2/5] fpga: dfl: Move the DFH definitions matthew.gerlach
2022-09-06 20:07   ` Andy Shevchenko
2022-09-07 21:01     ` matthew.gerlach
2022-09-07  5:08   ` Greg KH
2022-09-11 15:40     ` matthew.gerlach
2022-09-11 17:54       ` Geert Uytterhoeven
2022-09-11  8:04   ` Xu Yilun
2022-09-11 16:13     ` matthew.gerlach
2022-09-06 19:04 ` [PATCH v1 3/5] fpga: dfl: Add DFHv1 Register Definitions matthew.gerlach
2022-09-11  8:27   ` Xu Yilun
2022-09-11 16:21     ` matthew.gerlach
2022-09-06 19:04 ` [PATCH v1 4/5] fpga: dfl: add generic support for MSIX interrupts matthew.gerlach
2022-09-06 20:15   ` Andy Shevchenko
2022-09-07 21:37     ` matthew.gerlach
2022-09-08 11:04       ` Andy Shevchenko
2022-09-08 17:34         ` matthew.gerlach
2022-09-08 17:51           ` Andy Shevchenko
2022-09-08 19:28           ` Geert Uytterhoeven
2022-09-08 20:21             ` matthew.gerlach
2022-09-11  9:06   ` Xu Yilun
2022-09-06 19:04 ` matthew.gerlach [this message]
2022-09-06 20:24   ` [PATCH v1 5/5] tty: serial: 8250: add DFL bus driver for Altera 16550 Andy Shevchenko
2022-09-08 18:27     ` matthew.gerlach
2022-09-08 21:16       ` Andy Shevchenko
2022-09-11 15:56         ` matthew.gerlach
2022-09-12 10:54           ` Andy Shevchenko
2022-09-06 21:43   ` kernel test robot
2022-09-11  9:41   ` Xu Yilun
2022-09-12 15:29     ` matthew.gerlach
2022-09-13  2:48       ` Xu Yilun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220906190426.3139760-6-matthew.gerlach@linux.intel.com \
    --to=matthew.gerlach@linux.intel.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=basheer.ahmed.muddebihal@intel.com \
    --cc=corbet@lwn.net \
    --cc=geert+renesas@glider.be \
    --cc=gregkh@linuxfoundation.org \
    --cc=hao.wu@intel.com \
    --cc=jirislaby@kernel.org \
    --cc=johan@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=macro@orcam.me.uk \
    --cc=mdf@kernel.org \
    --cc=niklas.soderlund+renesas@ragnatech.se \
    --cc=phil.edworthy@renesas.com \
    --cc=russell.h.weight@intel.com \
    --cc=tianfei.zhang@intel.com \
    --cc=trix@redhat.com \
    --cc=yilun.xu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.