linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] LiteUART serial driver
@ 2019-10-23  9:46 Mateusz Holenko
  2019-10-23  9:46 ` [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX Mateusz Holenko
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Mateusz Holenko @ 2019-10-23  9:46 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial
  Cc: Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

This patchset introduces support for LiteUART
- serial device from LiteX SoC builder
(https://github.com/enjoy-digital/litex).

In the following patchset I will add
a new mor1kx-based (OpenRISC) platform that
uses this device.

Later I plan to extend this platform by
adding support for more devices from LiteX suite.

Changes in v2:
- binding description rewritten to a yaml schema file
- added litex.h header with common register access functions

Filip Kokosinski (3):
  dt-bindings: vendor: add vendor prefix for LiteX
  dt-bindings: serial: document LiteUART bindings
  drivers/tty/serial: add LiteUART driver

Mateusz Holenko (1):
  litex: add common LiteX header

 .../bindings/serial/litex,liteuart.yaml       |  38 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 MAINTAINERS                                   |   8 +
 drivers/tty/serial/Kconfig                    |  30 ++
 drivers/tty/serial/Makefile                   |   1 +
 drivers/tty/serial/liteuart.c                 | 373 ++++++++++++++++++
 include/linux/litex.h                         |  59 +++
 include/uapi/linux/serial_core.h              |   3 +
 8 files changed, 514 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/litex,liteuart.yaml
 create mode 100644 drivers/tty/serial/liteuart.c
 create mode 100644 include/linux/litex.h

-- 
2.23.0


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

* [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX
  2019-10-23  9:46 [PATCH v2 0/4] LiteUART serial driver Mateusz Holenko
@ 2019-10-23  9:46 ` Mateusz Holenko
  2019-10-25 23:36   ` Rob Herring
  2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: Mateusz Holenko @ 2019-10-23  9:46 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial
  Cc: Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

From: Filip Kokosinski <fkokosinski@internships.antmicro.com>

Add vendor prefix for LiteX SoC builder.

Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
---
No changes in v2.

 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 967e78c5ec0a..dae98f826290 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -537,6 +537,8 @@ patternProperties:
     description: Linux-specific binding
   "^linx,.*":
     description: Linx Technologies
+  "^litex,.*":
+    description: LiteX SoC builder
   "^lltc,.*":
     description: Linear Technology Corporation
   "^logicpd,.*":
-- 
2.23.0


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

* [PATCH v2 2/4] litex: add common LiteX header
  2019-10-23  9:46 [PATCH v2 0/4] LiteUART serial driver Mateusz Holenko
  2019-10-23  9:46 ` [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX Mateusz Holenko
@ 2019-10-23  9:47 ` Mateusz Holenko
  2019-10-26  0:03   ` Rob Herring
                     ` (2 more replies)
  2019-10-23  9:47 ` [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings Mateusz Holenko
  2019-10-23  9:47 ` [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver Mateusz Holenko
  3 siblings, 3 replies; 16+ messages in thread
From: Mateusz Holenko @ 2019-10-23  9:47 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial
  Cc: Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

It provides helper CSR access functions used by all
LiteX drivers.

Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
---
This commit has been introduced in v2 of the patchset.

 MAINTAINERS           |  6 +++++
 include/linux/litex.h | 59 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 include/linux/litex.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 296de2b51c83..eaa51209bfb2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9493,6 +9493,12 @@ F:	Documentation/misc-devices/lis3lv02d.rst
 F:	drivers/misc/lis3lv02d/
 F:	drivers/platform/x86/hp_accel.c
 
+LITEX PLATFORM
+M:	Karol Gugala <kgugala@antmicro.com>
+M:	Mateusz Holenko <mholenko@antmicro.com>
+S:	Maintained
+F:	include/linux/litex.h
+
 LIVE PATCHING
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
 M:	Jiri Kosina <jikos@kernel.org>
diff --git a/include/linux/litex.h b/include/linux/litex.h
new file mode 100644
index 000000000000..e793d2d7c881
--- /dev/null
+++ b/include/linux/litex.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Common LiteX header providing
+ * helper functions for accessing CSRs.
+ *
+ * Copyright (C) 2019 Antmicro <www.antmicro.com>
+ */
+
+#ifndef _LINUX_LITEX_H
+#define _LINUX_LITEX_H
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/compiler_types.h>
+
+#define LITEX_REG_SIZE             0x4
+#define LITEX_SUBREG_SIZE          0x1
+#define LITEX_SUBREG_SIZE_BIT      (LITEX_SUBREG_SIZE * 8)
+
+#ifdef __LITTLE_ENDIAN
+# define LITEX_READ_REG(addr)                  ioread32(addr)
+# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
+# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
+# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
+#else
+# define LITEX_READ_REG(addr)                  ioread32be(addr)
+# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
+# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
+# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
+#endif
+
+/* Helper functions for manipulating LiteX registers */
+
+static inline void litex_set_reg(void __iomem *reg, u32 reg_size, u32 val)
+{
+	u32 shifted_data, shift, i;
+
+	for (i = 0; i < reg_size; ++i) {
+		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
+		shifted_data = val >> shift;
+		LITEX_WRITE_REG(shifted_data, reg + (LITEX_REG_SIZE * i));
+	}
+}
+
+static inline u32 litex_get_reg(void __iomem *reg, u32 reg_size)
+{
+	u32 shifted_data, shift, i;
+	u32 result = 0;
+
+	for (i = 0; i < reg_size; ++i) {
+		shifted_data = LITEX_READ_REG(reg + (LITEX_REG_SIZE * i));
+		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
+		result |= (shifted_data << shift);
+	}
+
+	return result;
+}
+
+#endif /* _LINUX_LITEX_H */
-- 
2.23.0

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

* [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings
  2019-10-23  9:46 [PATCH v2 0/4] LiteUART serial driver Mateusz Holenko
  2019-10-23  9:46 ` [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX Mateusz Holenko
  2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
@ 2019-10-23  9:47 ` Mateusz Holenko
  2019-10-26  0:14   ` Rob Herring
  2019-10-23  9:47 ` [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver Mateusz Holenko
  3 siblings, 1 reply; 16+ messages in thread
From: Mateusz Holenko @ 2019-10-23  9:47 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial
  Cc: Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

From: Filip Kokosinski <fkokosinski@internships.antmicro.com>

Add documentation for LiteUART devicetree bindings.

Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
---
Changes in v2:
- binding description rewritten to a yaml schema file
- added interrupt line
- fixed unit address
- patch number changed from 2 to 3

 .../bindings/serial/litex,liteuart.yaml       | 38 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/litex,liteuart.yaml

diff --git a/Documentation/devicetree/bindings/serial/litex,liteuart.yaml b/Documentation/devicetree/bindings/serial/litex,liteuart.yaml
new file mode 100644
index 000000000000..87bf846b170a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/litex,liteuart.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/litex,liteuart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LiteUART serial controller
+
+maintainers:
+  - Karol Gugala <kgugala@antmicro.com>
+  - Mateusz Holenko <mholenko@antmicro.com>
+
+description: |
+  LiteUART serial controller is a part of LiteX FPGA SoC builder. It supports
+  multiple CPU architectures, currently including e.g. OpenRISC and RISC-V.
+
+properties:
+  compatible:
+    const: litex,liteuart
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    uart0: serial@e0001800 {
+      compatible = "litex,liteuart";
+      reg = <0xe0001800 0x100>;
+      interrupts = <2>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index eaa51209bfb2..1dc783c9edb7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9498,6 +9498,7 @@ M:	Karol Gugala <kgugala@antmicro.com>
 M:	Mateusz Holenko <mholenko@antmicro.com>
 S:	Maintained
 F:	include/linux/litex.h
+F:	Documentation/devicetree/bindings/*/litex,*.yaml
 
 LIVE PATCHING
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
-- 
2.23.0


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

* [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver
  2019-10-23  9:46 [PATCH v2 0/4] LiteUART serial driver Mateusz Holenko
                   ` (2 preceding siblings ...)
  2019-10-23  9:47 ` [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings Mateusz Holenko
@ 2019-10-23  9:47 ` Mateusz Holenko
  2019-10-26  0:13   ` Rob Herring
  3 siblings, 1 reply; 16+ messages in thread
From: Mateusz Holenko @ 2019-10-23  9:47 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial
  Cc: Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

From: Filip Kokosinski <fkokosinski@internships.antmicro.com>

This commit adds driver for the FPGA-based LiteUART serial controller
from LiteX SoC builder.

The current implementation supports LiteUART configured
for 32 bit data width and 8 bit CSR bus width.

It does not support IRQ.

Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
---
Changes in v2:
- used register access functions from newly introduced litex.h
- patch number changed from 3 to 4

 MAINTAINERS                      |   1 +
 drivers/tty/serial/Kconfig       |  30 +++
 drivers/tty/serial/Makefile      |   1 +
 drivers/tty/serial/liteuart.c    | 373 +++++++++++++++++++++++++++++++
 include/uapi/linux/serial_core.h |   3 +
 5 files changed, 408 insertions(+)
 create mode 100644 drivers/tty/serial/liteuart.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1dc783c9edb7..c24a37833e78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9499,6 +9499,7 @@ M:	Mateusz Holenko <mholenko@antmicro.com>
 S:	Maintained
 F:	include/linux/litex.h
 F:	Documentation/devicetree/bindings/*/litex,*.yaml
+F:	drivers/tty/serial/liteuart.c
 
 LIVE PATCHING
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 4789b5d62f63..b01fe12a1411 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1571,6 +1571,36 @@ config SERIAL_MILBEAUT_USIO_CONSOLE
 	  receives all kernel messages and warnings and which allows logins in
 	  single user mode).
 
+config SERIAL_LITEUART
+	tristate "LiteUART serial port support"
+	depends on HAS_IOMEM
+	depends on OF
+	select SERIAL_CORE
+	help
+	  This driver is for the FPGA-based LiteUART serial controller from LiteX
+	  SoC builder.
+
+	  Say 'Y' here if you wish to use the LiteUART serial controller.
+	  Otherwise, say 'N'.
+
+config SERIAL_LITEUART_NR_PORTS
+	int "Number of LiteUART ports"
+	depends on SERIAL_LITEUART
+	default "1"
+	help
+	  Set this to the number of serial ports you want the driver
+	  to support.
+
+config SERIAL_LITEUART_CONSOLE
+	bool "LiteUART serial port console support"
+	depends on SERIAL_LITEUART=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Say 'Y' here if you wish to use the FPGA-based LiteUART serial controller
+	  from LiteX SoC builder as the system console (the system console is the
+	  device which receives all kernel messages and warnings and which allows
+	  logins in single user mode). Otherwise, say 'N'.
+
 endmenu
 
 config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 863f47056539..c8d7e2046284 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_SERIAL_OWL)	+= owl-uart.o
 obj-$(CONFIG_SERIAL_RDA)	+= rda-uart.o
 obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
 obj-$(CONFIG_SERIAL_SIFIVE)	+= sifive.o
+obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o
 
 # GPIOLIB helpers for modem control lines
 obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
new file mode 100644
index 000000000000..e142f78df57a
--- /dev/null
+++ b/drivers/tty/serial/liteuart.c
@@ -0,0 +1,373 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LiteUART serial controller (LiteX) Driver
+ *
+ * Copyright (C) 2019 Antmicro Ltd <www.antmicro.com>
+ */
+
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/timer.h>
+#include <linux/tty_flip.h>
+#include <linux/litex.h>
+
+/* module-related defines */
+#define DRIVER_NAME	"liteuart"
+#define DRIVER_MAJOR	0
+#define DRIVER_MINOR	0
+#define DEV_NAME	"ttyLXU"
+
+/* base address offsets */
+#define OFF_RXTX	0x00
+#define OFF_TXFULL	0x04
+#define OFF_RXEMPTY	0x08
+#define OFF_EV_STATUS	0x0c
+#define OFF_EV_PENDING	0x10
+#define OFF_EV_ENABLE	0x14
+
+/* events */
+#define EV_TX	0x1
+#define EV_RX	0x2
+
+struct liteuart_port {
+	struct uart_port port;
+	struct timer_list timer;
+};
+
+#define to_liteuart_port(port)	container_of(port, struct liteuart_port, port)
+
+static struct liteuart_port liteuart_ports[CONFIG_SERIAL_LITEUART_NR_PORTS];
+
+#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
+static struct console liteuart_console;
+#endif
+
+static struct uart_driver liteuart_driver = {
+	.owner = THIS_MODULE,
+	.driver_name = DRIVER_NAME,
+	.dev_name = DEV_NAME,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.nr = CONFIG_SERIAL_LITEUART_NR_PORTS,
+#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
+	.cons = &liteuart_console,
+#endif
+};
+
+static void liteuart_timer(struct timer_list *t)
+{
+	struct liteuart_port *uart = from_timer(uart, t, timer);
+	struct uart_port *port = &uart->port;
+	unsigned char __iomem *membase = port->membase;
+	unsigned int flg = TTY_NORMAL;
+	int ch;
+	unsigned int status;
+
+	while ((status = !LITEX_READ_REG_OFF(membase, OFF_RXEMPTY)) == 1) {
+		ch = LITEX_READ_REG_OFF(membase, OFF_RXTX);
+		port->icount.rx++;
+
+		/* necessary for RXEMPTY to refresh its value */
+		LITEX_WRITE_REG_OFF(EV_TX | EV_RX, membase, OFF_EV_PENDING);
+
+		/* no overflow bits in status */
+		if (!(uart_handle_sysrq_char(port, ch)))
+			uart_insert_char(port, status, 0, ch, flg);
+
+		tty_flip_buffer_push(&port->state->port);
+	}
+
+	mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
+}
+
+static void liteuart_putchar(struct uart_port *port, int ch)
+{
+	while (LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
+		cpu_relax();
+
+	LITEX_WRITE_REG_OFF(ch, port->membase, OFF_RXTX);
+}
+
+static unsigned int liteuart_tx_empty(struct uart_port *port)
+{
+	/* not really tx empty, just checking if tx is not full */
+	if (!LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
+		return TIOCSER_TEMT;
+
+	return 0;
+}
+
+static void liteuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* modem control register is not present in LiteUART */
+}
+
+static unsigned int liteuart_get_mctrl(struct uart_port *port)
+{
+	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void liteuart_stop_tx(struct uart_port *port)
+{
+}
+
+static void liteuart_start_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned char ch;
+
+	if (unlikely(port->x_char)) {
+		LITEX_WRITE_REG_OFF(port->x_char, port->membase, OFF_RXTX);
+		port->icount.tx++;
+		port->x_char = 0;
+	} else if (!uart_circ_empty(xmit)) {
+		while (xmit->head != xmit->tail) {
+			ch = xmit->buf[xmit->tail];
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+			port->icount.tx++;
+			liteuart_putchar(port, ch);
+		}
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+}
+
+static void liteuart_stop_rx(struct uart_port *port)
+{
+	struct liteuart_port *uart = to_liteuart_port(port);
+
+	/* just delete timer */
+	del_timer(&uart->timer);
+}
+
+static void liteuart_break_ctl(struct uart_port *port, int break_state)
+{
+	/* LiteUART doesn't support sending break signal */
+}
+
+static int liteuart_startup(struct uart_port *port)
+{
+	struct liteuart_port *uart = to_liteuart_port(port);
+
+	/* disable events */
+	LITEX_WRITE_REG_OFF(0, port->membase, OFF_EV_ENABLE);
+
+	/* prepare timer for polling */
+	timer_setup(&uart->timer, liteuart_timer, 0);
+	mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
+
+	return 0;
+}
+
+static void liteuart_shutdown(struct uart_port *port)
+{
+}
+
+static void liteuart_set_termios(struct uart_port *port, struct ktermios *new,
+				 struct ktermios *old)
+{
+	unsigned int baud;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* update baudrate */
+	baud = uart_get_baud_rate(port, new, old, 0, 460800);
+	uart_update_timeout(port, new->c_cflag, baud);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *liteuart_type(struct uart_port *port)
+{
+	return (port->type == PORT_LITEUART) ? DRIVER_NAME : NULL;
+}
+
+static void liteuart_release_port(struct uart_port *port)
+{
+}
+
+static int liteuart_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void liteuart_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_LITEUART;
+}
+
+static int liteuart_verify_port(struct uart_port *port,
+				struct serial_struct *ser)
+{
+	if (port->type != PORT_UNKNOWN && ser->type != PORT_LITEUART)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct uart_ops liteuart_ops = {
+	.tx_empty	= liteuart_tx_empty,
+	.set_mctrl	= liteuart_set_mctrl,
+	.get_mctrl	= liteuart_get_mctrl,
+	.stop_tx	= liteuart_stop_tx,
+	.start_tx	= liteuart_start_tx,
+	.stop_rx	= liteuart_stop_rx,
+	.break_ctl	= liteuart_break_ctl,
+	.startup	= liteuart_startup,
+	.shutdown	= liteuart_shutdown,
+	.set_termios	= liteuart_set_termios,
+	.type		= liteuart_type,
+	.release_port	= liteuart_release_port,
+	.request_port	= liteuart_request_port,
+	.config_port	= liteuart_config_port,
+	.verify_port	= liteuart_verify_port,
+};
+
+static int liteuart_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct liteuart_port *uart;
+	struct uart_port *port;
+	int dev_id;
+
+	/* no device tree */
+	if (!np)
+		return -ENODEV;
+
+	dev_id = of_alias_get_id(np, "serial");
+	if (dev_id < 0 || dev_id >= CONFIG_SERIAL_LITEUART_NR_PORTS)
+		return -EINVAL;
+
+	uart = &liteuart_ports[dev_id];
+	port = &uart->port;
+
+	/* get {map,mem}base */
+	port->mapbase = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start;
+	port->membase = of_iomap(np, 0);
+	if (!port->membase)
+		return -ENXIO;
+
+	/* values not from device tree */
+	port->dev = &pdev->dev;
+	port->iotype = UPIO_MEM;
+	port->flags = UPF_BOOT_AUTOCONF;
+	port->ops = &liteuart_ops;
+	port->regshift = 2;
+	port->fifosize = 16;
+	port->iobase = 1;
+	port->type = PORT_UNKNOWN;
+	port->line = dev_id;
+
+	return uart_add_one_port(&liteuart_driver,
+				 &liteuart_ports[dev_id].port);
+}
+
+static int liteuart_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id liteuart_of_match[] = {
+	{ .compatible = "litex,liteuart" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, liteuart_of_match);
+
+static struct platform_driver liteuart_platform_driver = {
+	.probe = liteuart_probe,
+	.remove = liteuart_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(liteuart_of_match),
+	},
+};
+
+#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
+
+static void liteuart_console_write(struct console *co, const char *s,
+	unsigned int count)
+{
+	struct uart_port *port = &liteuart_ports[co->index].port;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	uart_console_write(port, s, count, liteuart_putchar);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int liteuart_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	port = &liteuart_ports[co->index].port;
+	if (!port->membase)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct console liteuart_console = {
+	.name = DRIVER_NAME,
+	.write = liteuart_console_write,
+	.device = uart_console_device,
+	.setup = liteuart_console_setup,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+	.data = &liteuart_driver,
+};
+
+static int __init liteuart_console_init(void)
+{
+	register_console(&liteuart_console);
+
+	return 0;
+}
+
+console_initcall(liteuart_console_init);
+#endif /* CONFIG_SERIAL_LITEUART_CONSOLE */
+
+static int __init liteuart_init(void)
+{
+	int res;
+
+	res = uart_register_driver(&liteuart_driver);
+	if (res)
+		return res;
+
+	res = platform_driver_register(&liteuart_platform_driver);
+	if (res) {
+		uart_unregister_driver(&liteuart_driver);
+		return res;
+	}
+
+	return 0;
+}
+
+static void __exit liteuart_exit(void)
+{
+	platform_driver_unregister(&liteuart_platform_driver);
+	uart_unregister_driver(&liteuart_driver);
+}
+
+module_init(liteuart_init);
+module_exit(liteuart_exit);
+
+MODULE_AUTHOR("Antmicro Ltd <www.antmicro.com>");
+MODULE_DESCRIPTION("LiteUART serial driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 0f4f87a6fd54..8fe6b0bf8014 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -293,4 +293,7 @@
 /* Freescale Linflex UART */
 #define PORT_LINFLEXUART	121
 
+/* LiteUART */
+#define PORT_LITEUART	122
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
2.23.0


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

* Re: [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX
  2019-10-23  9:46 ` [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX Mateusz Holenko
@ 2019-10-25 23:36   ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-10-25 23:36 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	linux-serial, Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

On Wed, 23 Oct 2019 11:46:54 +0200, Mateusz Holenko wrote:
> From: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> 
> Add vendor prefix for LiteX SoC builder.
> 
> Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> ---
> No changes in v2.
> 
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
@ 2019-10-26  0:03   ` Rob Herring
  2019-11-07  9:27     ` Mateusz Holenko
  2019-11-20 17:23   ` Gabriel L. Somlo
  2019-11-20 19:26   ` Greg Kroah-Hartman
  2 siblings, 1 reply; 16+ messages in thread
From: Rob Herring @ 2019-10-26  0:03 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	linux-serial, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> It provides helper CSR access functions used by all
> LiteX drivers.
> 
> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> ---
> This commit has been introduced in v2 of the patchset.
> 
>  MAINTAINERS           |  6 +++++
>  include/linux/litex.h | 59 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>  create mode 100644 include/linux/litex.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 296de2b51c83..eaa51209bfb2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9493,6 +9493,12 @@ F:	Documentation/misc-devices/lis3lv02d.rst
>  F:	drivers/misc/lis3lv02d/
>  F:	drivers/platform/x86/hp_accel.c
>  
> +LITEX PLATFORM
> +M:	Karol Gugala <kgugala@antmicro.com>
> +M:	Mateusz Holenko <mholenko@antmicro.com>
> +S:	Maintained
> +F:	include/linux/litex.h
> +
>  LIVE PATCHING
>  M:	Josh Poimboeuf <jpoimboe@redhat.com>
>  M:	Jiri Kosina <jikos@kernel.org>
> diff --git a/include/linux/litex.h b/include/linux/litex.h
> new file mode 100644
> index 000000000000..e793d2d7c881
> --- /dev/null
> +++ b/include/linux/litex.h
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Common LiteX header providing
> + * helper functions for accessing CSRs.
> + *
> + * Copyright (C) 2019 Antmicro <www.antmicro.com>
> + */
> +
> +#ifndef _LINUX_LITEX_H
> +#define _LINUX_LITEX_H
> +
> +#include <linux/io.h>
> +#include <linux/types.h>
> +#include <linux/compiler_types.h>
> +
> +#define LITEX_REG_SIZE             0x4
> +#define LITEX_SUBREG_SIZE          0x1
> +#define LITEX_SUBREG_SIZE_BIT      (LITEX_SUBREG_SIZE * 8)
> +
> +#ifdef __LITTLE_ENDIAN
> +# define LITEX_READ_REG(addr)                  ioread32(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> +#else
> +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)

Defining custom accessors makes it harder for others to understand 
the code. The __raw_readl/writel accessors are native endian, so use 
those. One difference though is they don't have a memory barrier, but 
based on the below functions, you may want to do your own barrier 
anyways. And if DMA is not involved you don't need the barriers either.

The _OFF variants don't add anything. LITEX_READ_REG(addr + off) is just 
as easy to read if not easier than LITEX_READ_REG_OFF(addr, off).

> +#endif
> +
> +/* Helper functions for manipulating LiteX registers */
> +
> +static inline void litex_set_reg(void __iomem *reg, u32 reg_size, u32 val)
> +{
> +	u32 shifted_data, shift, i;
> +
> +	for (i = 0; i < reg_size; ++i) {
> +		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> +		shifted_data = val >> shift;
> +		LITEX_WRITE_REG(shifted_data, reg + (LITEX_REG_SIZE * i));
> +	}
> +}

The problem with this is it hides whether you need to do any locking. 
Normally, you would assume a register access is atomic when it's not 
here. You could add locking in this function, but then you're doing 
locking even when not needed.

It doesn't look like you actually use this in your series, so maybe 
remove until you do.

> +
> +static inline u32 litex_get_reg(void __iomem *reg, u32 reg_size)
> +{
> +	u32 shifted_data, shift, i;
> +	u32 result = 0;
> +
> +	for (i = 0; i < reg_size; ++i) {
> +		shifted_data = LITEX_READ_REG(reg + (LITEX_REG_SIZE * i));
> +		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> +		result |= (shifted_data << shift);
> +	}
> +
> +	return result;
> +}
> +
> +#endif /* _LINUX_LITEX_H */
> -- 
> 2.23.0

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

* Re: [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver
  2019-10-23  9:47 ` [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver Mateusz Holenko
@ 2019-10-26  0:13   ` Rob Herring
  2019-11-07  9:33     ` Mateusz Holenko
  0 siblings, 1 reply; 16+ messages in thread
From: Rob Herring @ 2019-10-26  0:13 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	linux-serial, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

On Wed, Oct 23, 2019 at 11:47:23AM +0200, Mateusz Holenko wrote:
> From: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> 
> This commit adds driver for the FPGA-based LiteUART serial controller
> from LiteX SoC builder.
> 
> The current implementation supports LiteUART configured
> for 32 bit data width and 8 bit CSR bus width.
> 
> It does not support IRQ.
> 
> Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> ---
> Changes in v2:
> - used register access functions from newly introduced litex.h
> - patch number changed from 3 to 4
> 
>  MAINTAINERS                      |   1 +
>  drivers/tty/serial/Kconfig       |  30 +++
>  drivers/tty/serial/Makefile      |   1 +
>  drivers/tty/serial/liteuart.c    | 373 +++++++++++++++++++++++++++++++
>  include/uapi/linux/serial_core.h |   3 +
>  5 files changed, 408 insertions(+)
>  create mode 100644 drivers/tty/serial/liteuart.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1dc783c9edb7..c24a37833e78 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9499,6 +9499,7 @@ M:	Mateusz Holenko <mholenko@antmicro.com>
>  S:	Maintained
>  F:	include/linux/litex.h
>  F:	Documentation/devicetree/bindings/*/litex,*.yaml
> +F:	drivers/tty/serial/liteuart.c
>  
>  LIVE PATCHING
>  M:	Josh Poimboeuf <jpoimboe@redhat.com>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 4789b5d62f63..b01fe12a1411 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1571,6 +1571,36 @@ config SERIAL_MILBEAUT_USIO_CONSOLE
>  	  receives all kernel messages and warnings and which allows logins in
>  	  single user mode).
>  
> +config SERIAL_LITEUART
> +	tristate "LiteUART serial port support"
> +	depends on HAS_IOMEM
> +	depends on OF
> +	select SERIAL_CORE
> +	help
> +	  This driver is for the FPGA-based LiteUART serial controller from LiteX
> +	  SoC builder.
> +
> +	  Say 'Y' here if you wish to use the LiteUART serial controller.
> +	  Otherwise, say 'N'.
> +
> +config SERIAL_LITEUART_NR_PORTS
> +	int "Number of LiteUART ports"
> +	depends on SERIAL_LITEUART
> +	default "1"
> +	help
> +	  Set this to the number of serial ports you want the driver
> +	  to support.

It's better if the driver supports a dynamic number of ports.

> +
> +config SERIAL_LITEUART_CONSOLE
> +	bool "LiteUART serial port console support"
> +	depends on SERIAL_LITEUART=y
> +	select SERIAL_CORE_CONSOLE
> +	help
> +	  Say 'Y' here if you wish to use the FPGA-based LiteUART serial controller
> +	  from LiteX SoC builder as the system console (the system console is the
> +	  device which receives all kernel messages and warnings and which allows
> +	  logins in single user mode). Otherwise, say 'N'.
> +
>  endmenu
>  
>  config SERIAL_MCTRL_GPIO
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index 863f47056539..c8d7e2046284 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -89,6 +89,7 @@ obj-$(CONFIG_SERIAL_OWL)	+= owl-uart.o
>  obj-$(CONFIG_SERIAL_RDA)	+= rda-uart.o
>  obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
>  obj-$(CONFIG_SERIAL_SIFIVE)	+= sifive.o
> +obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o
>  
>  # GPIOLIB helpers for modem control lines
>  obj-$(CONFIG_SERIAL_MCTRL_GPIO)	+= serial_mctrl_gpio.o
> diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
> new file mode 100644
> index 000000000000..e142f78df57a
> --- /dev/null
> +++ b/drivers/tty/serial/liteuart.c
> @@ -0,0 +1,373 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * LiteUART serial controller (LiteX) Driver
> + *
> + * Copyright (C) 2019 Antmicro Ltd <www.antmicro.com>
> + */
> +
> +#include <linux/console.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/serial.h>
> +#include <linux/serial_core.h>
> +#include <linux/timer.h>
> +#include <linux/tty_flip.h>
> +#include <linux/litex.h>
> +
> +/* module-related defines */
> +#define DRIVER_NAME	"liteuart"
> +#define DRIVER_MAJOR	0
> +#define DRIVER_MINOR	0
> +#define DEV_NAME	"ttyLXU"
> +
> +/* base address offsets */
> +#define OFF_RXTX	0x00
> +#define OFF_TXFULL	0x04
> +#define OFF_RXEMPTY	0x08
> +#define OFF_EV_STATUS	0x0c
> +#define OFF_EV_PENDING	0x10
> +#define OFF_EV_ENABLE	0x14
> +
> +/* events */
> +#define EV_TX	0x1
> +#define EV_RX	0x2
> +
> +struct liteuart_port {
> +	struct uart_port port;
> +	struct timer_list timer;
> +};
> +
> +#define to_liteuart_port(port)	container_of(port, struct liteuart_port, port)
> +
> +static struct liteuart_port liteuart_ports[CONFIG_SERIAL_LITEUART_NR_PORTS];
> +
> +#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
> +static struct console liteuart_console;
> +#endif
> +
> +static struct uart_driver liteuart_driver = {
> +	.owner = THIS_MODULE,
> +	.driver_name = DRIVER_NAME,
> +	.dev_name = DEV_NAME,
> +	.major = DRIVER_MAJOR,
> +	.minor = DRIVER_MINOR,
> +	.nr = CONFIG_SERIAL_LITEUART_NR_PORTS,
> +#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
> +	.cons = &liteuart_console,
> +#endif
> +};
> +
> +static void liteuart_timer(struct timer_list *t)
> +{
> +	struct liteuart_port *uart = from_timer(uart, t, timer);
> +	struct uart_port *port = &uart->port;
> +	unsigned char __iomem *membase = port->membase;
> +	unsigned int flg = TTY_NORMAL;
> +	int ch;
> +	unsigned int status;
> +
> +	while ((status = !LITEX_READ_REG_OFF(membase, OFF_RXEMPTY)) == 1) {
> +		ch = LITEX_READ_REG_OFF(membase, OFF_RXTX);
> +		port->icount.rx++;
> +
> +		/* necessary for RXEMPTY to refresh its value */
> +		LITEX_WRITE_REG_OFF(EV_TX | EV_RX, membase, OFF_EV_PENDING);
> +
> +		/* no overflow bits in status */
> +		if (!(uart_handle_sysrq_char(port, ch)))
> +			uart_insert_char(port, status, 0, ch, flg);
> +
> +		tty_flip_buffer_push(&port->state->port);
> +	}
> +
> +	mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
> +}
> +
> +static void liteuart_putchar(struct uart_port *port, int ch)
> +{
> +	while (LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
> +		cpu_relax();
> +
> +	LITEX_WRITE_REG_OFF(ch, port->membase, OFF_RXTX);
> +}
> +
> +static unsigned int liteuart_tx_empty(struct uart_port *port)
> +{
> +	/* not really tx empty, just checking if tx is not full */
> +	if (!LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
> +		return TIOCSER_TEMT;
> +
> +	return 0;
> +}
> +
> +static void liteuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +	/* modem control register is not present in LiteUART */
> +}
> +
> +static unsigned int liteuart_get_mctrl(struct uart_port *port)
> +{
> +	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
> +}
> +
> +static void liteuart_stop_tx(struct uart_port *port)
> +{
> +}
> +
> +static void liteuart_start_tx(struct uart_port *port)
> +{
> +	struct circ_buf *xmit = &port->state->xmit;
> +	unsigned char ch;
> +
> +	if (unlikely(port->x_char)) {
> +		LITEX_WRITE_REG_OFF(port->x_char, port->membase, OFF_RXTX);
> +		port->icount.tx++;
> +		port->x_char = 0;
> +	} else if (!uart_circ_empty(xmit)) {
> +		while (xmit->head != xmit->tail) {
> +			ch = xmit->buf[xmit->tail];
> +			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> +			port->icount.tx++;
> +			liteuart_putchar(port, ch);
> +		}
> +	}
> +
> +	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> +		uart_write_wakeup(port);
> +}
> +
> +static void liteuart_stop_rx(struct uart_port *port)
> +{
> +	struct liteuart_port *uart = to_liteuart_port(port);
> +
> +	/* just delete timer */
> +	del_timer(&uart->timer);
> +}
> +
> +static void liteuart_break_ctl(struct uart_port *port, int break_state)
> +{
> +	/* LiteUART doesn't support sending break signal */
> +}
> +
> +static int liteuart_startup(struct uart_port *port)
> +{
> +	struct liteuart_port *uart = to_liteuart_port(port);
> +
> +	/* disable events */
> +	LITEX_WRITE_REG_OFF(0, port->membase, OFF_EV_ENABLE);
> +
> +	/* prepare timer for polling */
> +	timer_setup(&uart->timer, liteuart_timer, 0);
> +	mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
> +
> +	return 0;
> +}
> +
> +static void liteuart_shutdown(struct uart_port *port)
> +{
> +}
> +
> +static void liteuart_set_termios(struct uart_port *port, struct ktermios *new,
> +				 struct ktermios *old)
> +{
> +	unsigned int baud;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&port->lock, flags);
> +
> +	/* update baudrate */
> +	baud = uart_get_baud_rate(port, new, old, 0, 460800);
> +	uart_update_timeout(port, new->c_cflag, baud);
> +
> +	spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static const char *liteuart_type(struct uart_port *port)
> +{
> +	return (port->type == PORT_LITEUART) ? DRIVER_NAME : NULL;
> +}
> +
> +static void liteuart_release_port(struct uart_port *port)
> +{
> +}
> +
> +static int liteuart_request_port(struct uart_port *port)
> +{
> +	return 0;
> +}
> +
> +static void liteuart_config_port(struct uart_port *port, int flags)
> +{
> +	if (flags & UART_CONFIG_TYPE)
> +		port->type = PORT_LITEUART;
> +}
> +
> +static int liteuart_verify_port(struct uart_port *port,
> +				struct serial_struct *ser)
> +{
> +	if (port->type != PORT_UNKNOWN && ser->type != PORT_LITEUART)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static const struct uart_ops liteuart_ops = {
> +	.tx_empty	= liteuart_tx_empty,
> +	.set_mctrl	= liteuart_set_mctrl,
> +	.get_mctrl	= liteuart_get_mctrl,
> +	.stop_tx	= liteuart_stop_tx,
> +	.start_tx	= liteuart_start_tx,
> +	.stop_rx	= liteuart_stop_rx,
> +	.break_ctl	= liteuart_break_ctl,
> +	.startup	= liteuart_startup,
> +	.shutdown	= liteuart_shutdown,
> +	.set_termios	= liteuart_set_termios,
> +	.type		= liteuart_type,
> +	.release_port	= liteuart_release_port,
> +	.request_port	= liteuart_request_port,
> +	.config_port	= liteuart_config_port,
> +	.verify_port	= liteuart_verify_port,
> +};
> +
> +static int liteuart_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct liteuart_port *uart;
> +	struct uart_port *port;
> +	int dev_id;
> +
> +	/* no device tree */
> +	if (!np)
> +		return -ENODEV;
> +
> +	dev_id = of_alias_get_id(np, "serial");
> +	if (dev_id < 0 || dev_id >= CONFIG_SERIAL_LITEUART_NR_PORTS)
> +		return -EINVAL;

aliases should be optional. There's a helper to get a free index without 
an alias you can use.

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

* Re: [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings
  2019-10-23  9:47 ` [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings Mateusz Holenko
@ 2019-10-26  0:14   ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-10-26  0:14 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	linux-serial, Stafford Horne, Karol Gugala, Mateusz Holenko,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

On Wed, 23 Oct 2019 11:47:14 +0200, Mateusz Holenko wrote:
> From: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> 
> Add documentation for LiteUART devicetree bindings.
> 
> Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> ---
> Changes in v2:
> - binding description rewritten to a yaml schema file
> - added interrupt line
> - fixed unit address
> - patch number changed from 2 to 3
> 
>  .../bindings/serial/litex,liteuart.yaml       | 38 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/litex,liteuart.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-10-26  0:03   ` Rob Herring
@ 2019-11-07  9:27     ` Mateusz Holenko
  0 siblings, 0 replies; 16+ messages in thread
From: Mateusz Holenko @ 2019-11-07  9:27 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

sob., 26 paź 2019 o 02:03 Rob Herring <robh@kernel.org> napisał(a):
>
> On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> > It provides helper CSR access functions used by all
> > LiteX drivers.
> >
> > Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> > ---
> > This commit has been introduced in v2 of the patchset.
> >
> >  MAINTAINERS           |  6 +++++
> >  include/linux/litex.h | 59 +++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 65 insertions(+)
> >  create mode 100644 include/linux/litex.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 296de2b51c83..eaa51209bfb2 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9493,6 +9493,12 @@ F:     Documentation/misc-devices/lis3lv02d.rst
> >  F:   drivers/misc/lis3lv02d/
> >  F:   drivers/platform/x86/hp_accel.c
> >
> > +LITEX PLATFORM
> > +M:   Karol Gugala <kgugala@antmicro.com>
> > +M:   Mateusz Holenko <mholenko@antmicro.com>
> > +S:   Maintained
> > +F:   include/linux/litex.h
> > +
> >  LIVE PATCHING
> >  M:   Josh Poimboeuf <jpoimboe@redhat.com>
> >  M:   Jiri Kosina <jikos@kernel.org>
> > diff --git a/include/linux/litex.h b/include/linux/litex.h
> > new file mode 100644
> > index 000000000000..e793d2d7c881
> > --- /dev/null
> > +++ b/include/linux/litex.h
> > @@ -0,0 +1,59 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Common LiteX header providing
> > + * helper functions for accessing CSRs.
> > + *
> > + * Copyright (C) 2019 Antmicro <www.antmicro.com>
> > + */
> > +
> > +#ifndef _LINUX_LITEX_H
> > +#define _LINUX_LITEX_H
> > +
> > +#include <linux/io.h>
> > +#include <linux/types.h>
> > +#include <linux/compiler_types.h>
> > +
> > +#define LITEX_REG_SIZE             0x4
> > +#define LITEX_SUBREG_SIZE          0x1
> > +#define LITEX_SUBREG_SIZE_BIT      (LITEX_SUBREG_SIZE * 8)
> > +
> > +#ifdef __LITTLE_ENDIAN
> > +# define LITEX_READ_REG(addr)                  ioread32(addr)
> > +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> > +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> > +#else
> > +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> > +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> > +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
>
> Defining custom accessors makes it harder for others to understand
> the code. The __raw_readl/writel accessors are native endian, so use
> those. One difference though is they don't have a memory barrier, but
> based on the below functions, you may want to do your own barrier
> anyways. And if DMA is not involved you don't need the barriers either.

LiteX CSRs are always little endian (even when combined with a big endian CPU),
so using just __raw_readl/writel won't work in all cases. This is the reason why
we proposed a custom accessors defined based on host CPU endianness.
Would adding a comment explaining this be enough or do you have other ideas?

> The _OFF variants don't add anything. LITEX_READ_REG(addr + off) is just
> as easy to read if not easier than LITEX_READ_REG_OFF(addr, off).

I agree, LITEX_READ_REG/LITEX_WRITE_REG is enough.

> > +#endif
> > +
> > +/* Helper functions for manipulating LiteX registers */
> > +
> > +static inline void litex_set_reg(void __iomem *reg, u32 reg_size, u32 val)
> > +{
> > +     u32 shifted_data, shift, i;
> > +
> > +     for (i = 0; i < reg_size; ++i) {
> > +             shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> > +             shifted_data = val >> shift;
> > +             LITEX_WRITE_REG(shifted_data, reg + (LITEX_REG_SIZE * i));
> > +     }
> > +}
>
> The problem with this is it hides whether you need to do any locking.
> Normally, you would assume a register access is atomic when it's not
> here. You could add locking in this function, but then you're doing
> locking even when not needed.
>
> It doesn't look like you actually use this in your series, so maybe
> remove until you do.

That's right. I added those functions in advance, having in mind
further drivers,
but maybe it will be better to drop them for now and re-introduce later.

> > +
> > +static inline u32 litex_get_reg(void __iomem *reg, u32 reg_size)
> > +{
> > +     u32 shifted_data, shift, i;
> > +     u32 result = 0;
> > +
> > +     for (i = 0; i < reg_size; ++i) {
> > +             shifted_data = LITEX_READ_REG(reg + (LITEX_REG_SIZE * i));
> > +             shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> > +             result |= (shifted_data << shift);
> > +     }
> > +
> > +     return result;
> > +}
> > +
> > +#endif /* _LINUX_LITEX_H */
> > --
> > 2.23.0



--
Mateusz Holenko
Antmicro Ltd | www.antmicro.com
Roosevelta 22, 60-829 Poznan, Poland

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

* Re: [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver
  2019-10-26  0:13   ` Rob Herring
@ 2019-11-07  9:33     ` Mateusz Holenko
  0 siblings, 0 replies; 16+ messages in thread
From: Mateusz Holenko @ 2019-11-07  9:33 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, Greg Kroah-Hartman, Jiri Slaby, devicetree,
	open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

sob., 26 paź 2019 o 02:13 Rob Herring <robh@kernel.org> napisał(a):
>
> On Wed, Oct 23, 2019 at 11:47:23AM +0200, Mateusz Holenko wrote:
> > From: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> >
> > This commit adds driver for the FPGA-based LiteUART serial controller
> > from LiteX SoC builder.
> >
> > The current implementation supports LiteUART configured
> > for 32 bit data width and 8 bit CSR bus width.
> >
> > It does not support IRQ.
> >
> > Signed-off-by: Filip Kokosinski <fkokosinski@internships.antmicro.com>
> > Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> > ---
> > Changes in v2:
> > - used register access functions from newly introduced litex.h
> > - patch number changed from 3 to 4
> >
> >  MAINTAINERS                      |   1 +
> >  drivers/tty/serial/Kconfig       |  30 +++
> >  drivers/tty/serial/Makefile      |   1 +
> >  drivers/tty/serial/liteuart.c    | 373 +++++++++++++++++++++++++++++++
> >  include/uapi/linux/serial_core.h |   3 +
> >  5 files changed, 408 insertions(+)
> >  create mode 100644 drivers/tty/serial/liteuart.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 1dc783c9edb7..c24a37833e78 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9499,6 +9499,7 @@ M:      Mateusz Holenko <mholenko@antmicro.com>
> >  S:   Maintained
> >  F:   include/linux/litex.h
> >  F:   Documentation/devicetree/bindings/*/litex,*.yaml
> > +F:   drivers/tty/serial/liteuart.c
> >
> >  LIVE PATCHING
> >  M:   Josh Poimboeuf <jpoimboe@redhat.com>
> > diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> > index 4789b5d62f63..b01fe12a1411 100644
> > --- a/drivers/tty/serial/Kconfig
> > +++ b/drivers/tty/serial/Kconfig
> > @@ -1571,6 +1571,36 @@ config SERIAL_MILBEAUT_USIO_CONSOLE
> >         receives all kernel messages and warnings and which allows logins in
> >         single user mode).
> >
> > +config SERIAL_LITEUART
> > +     tristate "LiteUART serial port support"
> > +     depends on HAS_IOMEM
> > +     depends on OF
> > +     select SERIAL_CORE
> > +     help
> > +       This driver is for the FPGA-based LiteUART serial controller from LiteX
> > +       SoC builder.
> > +
> > +       Say 'Y' here if you wish to use the LiteUART serial controller.
> > +       Otherwise, say 'N'.
> > +
> > +config SERIAL_LITEUART_NR_PORTS
> > +     int "Number of LiteUART ports"
> > +     depends on SERIAL_LITEUART
> > +     default "1"
> > +     help
> > +       Set this to the number of serial ports you want the driver
> > +       to support.
>
> It's better if the driver supports a dynamic number of ports.

Do you mean that the number of ports should be taken from the device
tree when booting the kernel?
This is exactly how it works right now. The SERIAL_LITEUART_NR_PORTS just
defines the maximum number of supported ports.
I can rename the config to SERIAL_LITEUART_MAX_NR_PORTS to make it
clearer, what do you think?

> > +
> > +config SERIAL_LITEUART_CONSOLE
> > +     bool "LiteUART serial port console support"
> > +     depends on SERIAL_LITEUART=y
> > +     select SERIAL_CORE_CONSOLE
> > +     help
> > +       Say 'Y' here if you wish to use the FPGA-based LiteUART serial controller
> > +       from LiteX SoC builder as the system console (the system console is the
> > +       device which receives all kernel messages and warnings and which allows
> > +       logins in single user mode). Otherwise, say 'N'.
> > +
> >  endmenu
> >
> >  config SERIAL_MCTRL_GPIO
> > diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> > index 863f47056539..c8d7e2046284 100644
> > --- a/drivers/tty/serial/Makefile
> > +++ b/drivers/tty/serial/Makefile
> > @@ -89,6 +89,7 @@ obj-$(CONFIG_SERIAL_OWL)    += owl-uart.o
> >  obj-$(CONFIG_SERIAL_RDA)     += rda-uart.o
> >  obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
> >  obj-$(CONFIG_SERIAL_SIFIVE)  += sifive.o
> > +obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o
> >
> >  # GPIOLIB helpers for modem control lines
> >  obj-$(CONFIG_SERIAL_MCTRL_GPIO)      += serial_mctrl_gpio.o
> > diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
> > new file mode 100644
> > index 000000000000..e142f78df57a
> > --- /dev/null
> > +++ b/drivers/tty/serial/liteuart.c
> > @@ -0,0 +1,373 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * LiteUART serial controller (LiteX) Driver
> > + *
> > + * Copyright (C) 2019 Antmicro Ltd <www.antmicro.com>
> > + */
> > +
> > +#include <linux/console.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/serial.h>
> > +#include <linux/serial_core.h>
> > +#include <linux/timer.h>
> > +#include <linux/tty_flip.h>
> > +#include <linux/litex.h>
> > +
> > +/* module-related defines */
> > +#define DRIVER_NAME  "liteuart"
> > +#define DRIVER_MAJOR 0
> > +#define DRIVER_MINOR 0
> > +#define DEV_NAME     "ttyLXU"
> > +
> > +/* base address offsets */
> > +#define OFF_RXTX     0x00
> > +#define OFF_TXFULL   0x04
> > +#define OFF_RXEMPTY  0x08
> > +#define OFF_EV_STATUS        0x0c
> > +#define OFF_EV_PENDING       0x10
> > +#define OFF_EV_ENABLE        0x14
> > +
> > +/* events */
> > +#define EV_TX        0x1
> > +#define EV_RX        0x2
> > +
> > +struct liteuart_port {
> > +     struct uart_port port;
> > +     struct timer_list timer;
> > +};
> > +
> > +#define to_liteuart_port(port)       container_of(port, struct liteuart_port, port)
> > +
> > +static struct liteuart_port liteuart_ports[CONFIG_SERIAL_LITEUART_NR_PORTS];
> > +
> > +#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
> > +static struct console liteuart_console;
> > +#endif
> > +
> > +static struct uart_driver liteuart_driver = {
> > +     .owner = THIS_MODULE,
> > +     .driver_name = DRIVER_NAME,
> > +     .dev_name = DEV_NAME,
> > +     .major = DRIVER_MAJOR,
> > +     .minor = DRIVER_MINOR,
> > +     .nr = CONFIG_SERIAL_LITEUART_NR_PORTS,
> > +#ifdef CONFIG_SERIAL_LITEUART_CONSOLE
> > +     .cons = &liteuart_console,
> > +#endif
> > +};
> > +
> > +static void liteuart_timer(struct timer_list *t)
> > +{
> > +     struct liteuart_port *uart = from_timer(uart, t, timer);
> > +     struct uart_port *port = &uart->port;
> > +     unsigned char __iomem *membase = port->membase;
> > +     unsigned int flg = TTY_NORMAL;
> > +     int ch;
> > +     unsigned int status;
> > +
> > +     while ((status = !LITEX_READ_REG_OFF(membase, OFF_RXEMPTY)) == 1) {
> > +             ch = LITEX_READ_REG_OFF(membase, OFF_RXTX);
> > +             port->icount.rx++;
> > +
> > +             /* necessary for RXEMPTY to refresh its value */
> > +             LITEX_WRITE_REG_OFF(EV_TX | EV_RX, membase, OFF_EV_PENDING);
> > +
> > +             /* no overflow bits in status */
> > +             if (!(uart_handle_sysrq_char(port, ch)))
> > +                     uart_insert_char(port, status, 0, ch, flg);
> > +
> > +             tty_flip_buffer_push(&port->state->port);
> > +     }
> > +
> > +     mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
> > +}
> > +
> > +static void liteuart_putchar(struct uart_port *port, int ch)
> > +{
> > +     while (LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
> > +             cpu_relax();
> > +
> > +     LITEX_WRITE_REG_OFF(ch, port->membase, OFF_RXTX);
> > +}
> > +
> > +static unsigned int liteuart_tx_empty(struct uart_port *port)
> > +{
> > +     /* not really tx empty, just checking if tx is not full */
> > +     if (!LITEX_READ_REG_OFF(port->membase, OFF_TXFULL))
> > +             return TIOCSER_TEMT;
> > +
> > +     return 0;
> > +}
> > +
> > +static void liteuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> > +{
> > +     /* modem control register is not present in LiteUART */
> > +}
> > +
> > +static unsigned int liteuart_get_mctrl(struct uart_port *port)
> > +{
> > +     return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
> > +}
> > +
> > +static void liteuart_stop_tx(struct uart_port *port)
> > +{
> > +}
> > +
> > +static void liteuart_start_tx(struct uart_port *port)
> > +{
> > +     struct circ_buf *xmit = &port->state->xmit;
> > +     unsigned char ch;
> > +
> > +     if (unlikely(port->x_char)) {
> > +             LITEX_WRITE_REG_OFF(port->x_char, port->membase, OFF_RXTX);
> > +             port->icount.tx++;
> > +             port->x_char = 0;
> > +     } else if (!uart_circ_empty(xmit)) {
> > +             while (xmit->head != xmit->tail) {
> > +                     ch = xmit->buf[xmit->tail];
> > +                     xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
> > +                     port->icount.tx++;
> > +                     liteuart_putchar(port, ch);
> > +             }
> > +     }
> > +
> > +     if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> > +             uart_write_wakeup(port);
> > +}
> > +
> > +static void liteuart_stop_rx(struct uart_port *port)
> > +{
> > +     struct liteuart_port *uart = to_liteuart_port(port);
> > +
> > +     /* just delete timer */
> > +     del_timer(&uart->timer);
> > +}
> > +
> > +static void liteuart_break_ctl(struct uart_port *port, int break_state)
> > +{
> > +     /* LiteUART doesn't support sending break signal */
> > +}
> > +
> > +static int liteuart_startup(struct uart_port *port)
> > +{
> > +     struct liteuart_port *uart = to_liteuart_port(port);
> > +
> > +     /* disable events */
> > +     LITEX_WRITE_REG_OFF(0, port->membase, OFF_EV_ENABLE);
> > +
> > +     /* prepare timer for polling */
> > +     timer_setup(&uart->timer, liteuart_timer, 0);
> > +     mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
> > +
> > +     return 0;
> > +}
> > +
> > +static void liteuart_shutdown(struct uart_port *port)
> > +{
> > +}
> > +
> > +static void liteuart_set_termios(struct uart_port *port, struct ktermios *new,
> > +                              struct ktermios *old)
> > +{
> > +     unsigned int baud;
> > +     unsigned long flags;
> > +
> > +     spin_lock_irqsave(&port->lock, flags);
> > +
> > +     /* update baudrate */
> > +     baud = uart_get_baud_rate(port, new, old, 0, 460800);
> > +     uart_update_timeout(port, new->c_cflag, baud);
> > +
> > +     spin_unlock_irqrestore(&port->lock, flags);
> > +}
> > +
> > +static const char *liteuart_type(struct uart_port *port)
> > +{
> > +     return (port->type == PORT_LITEUART) ? DRIVER_NAME : NULL;
> > +}
> > +
> > +static void liteuart_release_port(struct uart_port *port)
> > +{
> > +}
> > +
> > +static int liteuart_request_port(struct uart_port *port)
> > +{
> > +     return 0;
> > +}
> > +
> > +static void liteuart_config_port(struct uart_port *port, int flags)
> > +{
> > +     if (flags & UART_CONFIG_TYPE)
> > +             port->type = PORT_LITEUART;
> > +}
> > +
> > +static int liteuart_verify_port(struct uart_port *port,
> > +                             struct serial_struct *ser)
> > +{
> > +     if (port->type != PORT_UNKNOWN && ser->type != PORT_LITEUART)
> > +             return -EINVAL;
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct uart_ops liteuart_ops = {
> > +     .tx_empty       = liteuart_tx_empty,
> > +     .set_mctrl      = liteuart_set_mctrl,
> > +     .get_mctrl      = liteuart_get_mctrl,
> > +     .stop_tx        = liteuart_stop_tx,
> > +     .start_tx       = liteuart_start_tx,
> > +     .stop_rx        = liteuart_stop_rx,
> > +     .break_ctl      = liteuart_break_ctl,
> > +     .startup        = liteuart_startup,
> > +     .shutdown       = liteuart_shutdown,
> > +     .set_termios    = liteuart_set_termios,
> > +     .type           = liteuart_type,
> > +     .release_port   = liteuart_release_port,
> > +     .request_port   = liteuart_request_port,
> > +     .config_port    = liteuart_config_port,
> > +     .verify_port    = liteuart_verify_port,
> > +};
> > +
> > +static int liteuart_probe(struct platform_device *pdev)
> > +{
> > +     struct device_node *np = pdev->dev.of_node;
> > +     struct liteuart_port *uart;
> > +     struct uart_port *port;
> > +     int dev_id;
> > +
> > +     /* no device tree */
> > +     if (!np)
> > +             return -ENODEV;
> > +
> > +     dev_id = of_alias_get_id(np, "serial");
> > +     if (dev_id < 0 || dev_id >= CONFIG_SERIAL_LITEUART_NR_PORTS)
> > +             return -EINVAL;
>
> aliases should be optional. There's a helper to get a free index without
> an alias you can use.

Sure, we will fix it in v4.


-- 
Mateusz Holenko
Antmicro Ltd | www.antmicro.com
Roosevelta 22, 60-829 Poznan, Poland

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
  2019-10-26  0:03   ` Rob Herring
@ 2019-11-20 17:23   ` Gabriel L. Somlo
  2019-11-20 19:26   ` Greg Kroah-Hartman
  2 siblings, 0 replies; 16+ messages in thread
From: Gabriel L. Somlo @ 2019-11-20 17:23 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Rob Herring, Mark Rutland, Greg Kroah-Hartman, Jiri Slaby,
	devicetree, linux-serial, Stafford Horne, Karol Gugala,
	Mateusz Holenko, Mauro Carvalho Chehab, David S. Miller,
	Paul E. McKenney, Filip Kokosinski, Joel Stanley,
	Jonathan Cameron, Maxime Ripard, Shawn Guo, Heiko Stuebner,
	Sam Ravnborg, Icenowy Zheng, Laurent Pinchart, linux-kernel

> It provides helper CSR access functions used by all
> LiteX drivers.
> 
> Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> ---
> This commit has been introduced in v2 of the patchset.
> 
>  MAINTAINERS           |  6 +++++
>  include/linux/litex.h | 59 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>  create mode 100644 include/linux/litex.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 296de2b51c83..eaa51209bfb2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9493,6 +9493,12 @@ F:	Documentation/misc-devices/lis3lv02d.rst
>  F:	drivers/misc/lis3lv02d/
>  F:	drivers/platform/x86/hp_accel.c
>  
> +LITEX PLATFORM
> +M:	Karol Gugala <kgugala@antmicro.com>
> +M:	Mateusz Holenko <mholenko@antmicro.com>
> +S:	Maintained
> +F:	include/linux/litex.h
> +
>  LIVE PATCHING
>  M:	Josh Poimboeuf <jpoimboe@redhat.com>
>  M:	Jiri Kosina <jikos@kernel.org>
> diff --git a/include/linux/litex.h b/include/linux/litex.h
> new file mode 100644
> index 000000000000..e793d2d7c881
> --- /dev/null
> +++ b/include/linux/litex.h
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Common LiteX header providing
> + * helper functions for accessing CSRs.
> + *
> + * Copyright (C) 2019 Antmicro <www.antmicro.com>
> + */
> +
> +#ifndef _LINUX_LITEX_H
> +#define _LINUX_LITEX_H
> +
> +#include <linux/io.h>
> +#include <linux/types.h>
> +#include <linux/compiler_types.h>
> +
> +#define LITEX_REG_SIZE             0x4
> +#define LITEX_SUBREG_SIZE          0x1
> +#define LITEX_SUBREG_SIZE_BIT      (LITEX_SUBREG_SIZE * 8)

Please be aware that LiteX supports "LITEX_SUBREG_SIZE" of up to 4,
and might go even as far as 8 in the near future. Hard coding this
here might be short sighted.

A good alternative might be to have "litex_subreg_size" or
"mmio-dw-bytes" passed in via a DT property of the SoC node, as
illustrated here:

https://github.com/litex-hub/linux-on-litex-vexriscv/pull/60

Thanks,
--Gabriel

> +
> +#ifdef __LITTLE_ENDIAN
> +# define LITEX_READ_REG(addr)                  ioread32(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> +#else
> +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
> +#endif
> +
> +/* Helper functions for manipulating LiteX registers */
> +
> +static inline void litex_set_reg(void __iomem *reg, u32 reg_size, u32 val)
> +{
> +	u32 shifted_data, shift, i;
> +
> +	for (i = 0; i < reg_size; ++i) {
> +		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> +		shifted_data = val >> shift;
> +		LITEX_WRITE_REG(shifted_data, reg + (LITEX_REG_SIZE * i));
> +	}
> +}
> +
> +static inline u32 litex_get_reg(void __iomem *reg, u32 reg_size)
> +{
> +	u32 shifted_data, shift, i;
> +	u32 result = 0;
> +
> +	for (i = 0; i < reg_size; ++i) {
> +		shifted_data = LITEX_READ_REG(reg + (LITEX_REG_SIZE * i));
> +		shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
> +		result |= (shifted_data << shift);
> +	}
> +
> +	return result;
> +}
> +
> +#endif /* _LINUX_LITEX_H */

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
  2019-10-26  0:03   ` Rob Herring
  2019-11-20 17:23   ` Gabriel L. Somlo
@ 2019-11-20 19:26   ` Greg Kroah-Hartman
  2019-11-26  9:02     ` Mateusz Holenko
  2 siblings, 1 reply; 16+ messages in thread
From: Greg Kroah-Hartman @ 2019-11-20 19:26 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Rob Herring, Mark Rutland, Jiri Slaby, devicetree, linux-serial,
	Stafford Horne, Karol Gugala, Mauro Carvalho Chehab,
	David S. Miller, Paul E. McKenney, Filip Kokosinski,
	Joel Stanley, Jonathan Cameron, Maxime Ripard, Shawn Guo,
	Heiko Stuebner, Sam Ravnborg, Icenowy Zheng, Laurent Pinchart,
	linux-kernel

On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> +#ifdef __LITTLE_ENDIAN
> +# define LITEX_READ_REG(addr)                  ioread32(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> +#else
> +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
> +#endif

I just noticed this.

Ick, this is not good.  You will run into problems in the future with
this, I can guarantee it.  What about systems where the CPU is one
endian and the hardware in the other?  It will happen trust us.

Make these real functions (inline is nice) and pass in the pointer to
the device so you can test for it and call the correct function based on
the cpu/hardware type.

And what about bitfields?  What endian are they for your
system/hardware?

Almost no kernel code should EVER be testing __LITTLE_ENDIAN, don't add
to it as it is not a good idea.

thanks,

greg k-h

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-11-20 19:26   ` Greg Kroah-Hartman
@ 2019-11-26  9:02     ` Mateusz Holenko
  2019-11-26  9:19       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 16+ messages in thread
From: Mateusz Holenko @ 2019-11-26  9:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Rob Herring, Mark Rutland, Jiri Slaby, devicetree,
	open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

śr., 20 lis 2019 o 20:26 Greg Kroah-Hartman
<gregkh@linuxfoundation.org> napisał(a):
>
> On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> > +#ifdef __LITTLE_ENDIAN
> > +# define LITEX_READ_REG(addr)                  ioread32(addr)
> > +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> > +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> > +#else
> > +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> > +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> > +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
> > +#endif
>
> I just noticed this.
>
> Ick, this is not good.  You will run into problems in the future with
> this, I can guarantee it.  What about systems where the CPU is one
> endian and the hardware in the other?  It will happen trust us.

As mentioned in the previous comment, LiteX CSRs are guaranteed to be
always little-endian - this includes configurations with both
big-endian and little-endian CPUs.

The aim of including the ifdef section was exactly to target situation
where endianness is different for CPU and devices. As such this
approach *should* work.

> Make these real functions (inline is nice) and pass in the pointer to
> the device so you can test for it and call the correct function based on
> the cpu/hardware type.
>
> And what about bitfields?  What endian are they for your
> system/hardware?
>
> Almost no kernel code should EVER be testing __LITTLE_ENDIAN, don't add
> to it as it is not a good idea.

If I understand correctly, you suggest to replace compile-time
ifdefing with probing the endianness in the runtime (by reading some
register that should return a known value, say 1, and testing how bits
are arranged). This is a good idea, as it protects against breaking an
always-little-endian property of LiteX CSRs in the future.

I'll include this in the next version of the patchset.

> thanks,
>
> greg k-h

Thanks for your comments!

-- 
Mateusz Holenko
Antmicro Ltd | www.antmicro.com
Roosevelta 22, 60-829 Poznan, Poland

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-11-26  9:02     ` Mateusz Holenko
@ 2019-11-26  9:19       ` Greg Kroah-Hartman
  2019-11-29 15:39         ` Mateusz Holenko
  0 siblings, 1 reply; 16+ messages in thread
From: Greg Kroah-Hartman @ 2019-11-26  9:19 UTC (permalink / raw)
  To: Mateusz Holenko
  Cc: Rob Herring, Mark Rutland, Jiri Slaby, devicetree,
	open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

On Tue, Nov 26, 2019 at 10:02:18AM +0100, Mateusz Holenko wrote:
> śr., 20 lis 2019 o 20:26 Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> napisał(a):
> >
> > On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> > > +#ifdef __LITTLE_ENDIAN
> > > +# define LITEX_READ_REG(addr)                  ioread32(addr)
> > > +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> > > +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> > > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> > > +#else
> > > +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> > > +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> > > +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> > > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
> > > +#endif
> >
> > I just noticed this.
> >
> > Ick, this is not good.  You will run into problems in the future with
> > this, I can guarantee it.  What about systems where the CPU is one
> > endian and the hardware in the other?  It will happen trust us.
> 
> As mentioned in the previous comment, LiteX CSRs are guaranteed to be
> always little-endian - this includes configurations with both
> big-endian and little-endian CPUs.

What enforces that guarantee?

> The aim of including the ifdef section was exactly to target situation
> where endianness is different for CPU and devices. As such this
> approach *should* work.

"should" :)

We have seen it happen all the time that some hardware team hooks this
up backwards, no matter what the "spec" required.  So be careful here.

good luck!

greg k-h

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

* Re: [PATCH v2 2/4] litex: add common LiteX header
  2019-11-26  9:19       ` Greg Kroah-Hartman
@ 2019-11-29 15:39         ` Mateusz Holenko
  0 siblings, 0 replies; 16+ messages in thread
From: Mateusz Holenko @ 2019-11-29 15:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Rob Herring, Mark Rutland, Jiri Slaby, devicetree,
	open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
	Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
	Filip Kokosinski, Joel Stanley, Jonathan Cameron, Maxime Ripard,
	Shawn Guo, Heiko Stuebner, Sam Ravnborg, Icenowy Zheng,
	Laurent Pinchart, linux-kernel

wt., 26 lis 2019 o 10:19 Greg Kroah-Hartman
<gregkh@linuxfoundation.org> napisał(a):
>
> On Tue, Nov 26, 2019 at 10:02:18AM +0100, Mateusz Holenko wrote:
> > śr., 20 lis 2019 o 20:26 Greg Kroah-Hartman
> > <gregkh@linuxfoundation.org> napisał(a):
> > >
> > > On Wed, Oct 23, 2019 at 11:47:04AM +0200, Mateusz Holenko wrote:
> > > > +#ifdef __LITTLE_ENDIAN
> > > > +# define LITEX_READ_REG(addr)                  ioread32(addr)
> > > > +# define LITEX_READ_REG_OFF(addr, off)         ioread32(addr + off)
> > > > +# define LITEX_WRITE_REG(val, addr)            iowrite32(val, addr)
> > > > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32(val, addr + off)
> > > > +#else
> > > > +# define LITEX_READ_REG(addr)                  ioread32be(addr)
> > > > +# define LITEX_READ_REG_OFF(addr, off)         ioread32be(addr + off)
> > > > +# define LITEX_WRITE_REG(val, addr)            iowrite32be(val, addr)
> > > > +# define LITEX_WRITE_REG_OFF(val, addr, off)   iowrite32be(val, addr + off)
> > > > +#endif
> > >
> > > I just noticed this.
> > >
> > > Ick, this is not good.  You will run into problems in the future with
> > > this, I can guarantee it.  What about systems where the CPU is one
> > > endian and the hardware in the other?  It will happen trust us.
> >
> > As mentioned in the previous comment, LiteX CSRs are guaranteed to be
> > always little-endian - this includes configurations with both
> > big-endian and little-endian CPUs.
>
> What enforces that guarantee?

liteuart is na IP core that comes as a part of a design generated and
configured by LiteX SoC builder
(https://github.com/enjoy-digital/litex). Current implementation of
LiteX generates systems in such a way that CSRs in peripherals are
little-endian regardless of a softcore CPU used (available options
cover both little-endian and big-endian CPU cores). Liteuart is a part
of the LiteX project and is probably not usable outside of it.

I was digging through the code and documentation to verify that the
always-little-endian-CSR behaviour is "guaranteed", but - to my
surprise - couldn't find anything. It seems to be simply an
implementation detail that might (maybe?) change in the future.

In this context your suggestion about probing things dynamically seems
to be even more relevant.

> > The aim of including the ifdef section was exactly to target situation
> > where endianness is different for CPU and devices. As such this
> > approach *should* work.
>
> "should" :)
>
> We have seen it happen all the time that some hardware team hooks this
> up backwards, no matter what the "spec" required.  So be careful here.
>
> good luck!
>
> greg k-h



-- 
Mateusz Holenko
Antmicro Ltd | www.antmicro.com
Roosevelta 22, 60-829 Poznan, Poland

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

end of thread, other threads:[~2019-11-29 15:39 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-23  9:46 [PATCH v2 0/4] LiteUART serial driver Mateusz Holenko
2019-10-23  9:46 ` [PATCH v2 1/4] dt-bindings: vendor: add vendor prefix for LiteX Mateusz Holenko
2019-10-25 23:36   ` Rob Herring
2019-10-23  9:47 ` [PATCH v2 2/4] litex: add common LiteX header Mateusz Holenko
2019-10-26  0:03   ` Rob Herring
2019-11-07  9:27     ` Mateusz Holenko
2019-11-20 17:23   ` Gabriel L. Somlo
2019-11-20 19:26   ` Greg Kroah-Hartman
2019-11-26  9:02     ` Mateusz Holenko
2019-11-26  9:19       ` Greg Kroah-Hartman
2019-11-29 15:39         ` Mateusz Holenko
2019-10-23  9:47 ` [PATCH v2 3/4] dt-bindings: serial: document LiteUART bindings Mateusz Holenko
2019-10-26  0:14   ` Rob Herring
2019-10-23  9:47 ` [PATCH v2 4/4] drivers/tty/serial: add LiteUART driver Mateusz Holenko
2019-10-26  0:13   ` Rob Herring
2019-11-07  9:33     ` Mateusz Holenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).