From patchwork Wed Jan 23 10:28:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1029864 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jFX+E7Xs"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43l1hp1kfRz9s7h for ; Wed, 23 Jan 2019 21:28:26 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727302AbfAWK2Z (ORCPT ); Wed, 23 Jan 2019 05:28:25 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:35835 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726207AbfAWK2Z (ORCPT ); Wed, 23 Jan 2019 05:28:25 -0500 Received: by mail-wm1-f66.google.com with SMTP id t200so1436346wmt.0; Wed, 23 Jan 2019 02:28:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TlbHTmIMzaAHQga/bhk4fz7pIJkLJdzOm9HKY5RROAs=; b=jFX+E7Xs2jMPO0pEPU4KxuHlyqdeK79Np85zyjGHyYWzQzUR1bwcImFFthUDLyHz3S BM/J5CC0GstWnPsqHv6QckkZUpMPsQ/rH0H1o8jQS+5a8NtoeNbB/hBXxWGjUcMl0eDL xOTQVC1xKGebH0SHHmgRvtuJr/PS+nJvna9qTlBm19tIGiD+ZKQj+wHSSkucvlmUboCn fug+Bufv/dugy+Di83D2bJE3L7Ic9bcyutct28gesMTAFuyX057tACBIpPaSq+mDIdHj wCnYECNvrTVDv9qyYqU+9XZlmUK09OQeGqRgXifO6tNF4apUNnO3qqMkdWKVl2lohHmm MEMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TlbHTmIMzaAHQga/bhk4fz7pIJkLJdzOm9HKY5RROAs=; b=C3Uh6DfFjw1IX7gNXyCar9tZjK807Sqo7Hn3yD3cWyNv4cONcJg4OeQwn0yyje4/bj rvTpF0l1Kr4YcslwfbkZYy6cMdI7KBfWoo1XfHhi1wq0BQLniHtf6YEi6h+CKEFP09CC m+sJ0rLEyXhdp6Bg81GXr8+lhNA2bP3ZBGMqYKKumlDUpyuR8pODkrkmIo1LYGEXsk4E LIEDX5tsFISRpO9ZTPXFAnzd0JhkOvYbK/Wm/nie+/1gm2kfcSK5SVcolEwePP7v4Il9 j2fiKyX1+K7J4MNwjAa+CfwJFtOygfsQk4M9tn5ktwD3eKuF/O6wRLKoyuxp+nhpReJm zpJA== X-Gm-Message-State: AJcUukc8neZ/rDtf5nnT8gCIzulW7o/Y5VjZD90ZOVJFS8qVbWC4FbwZ 9aW3N+qm2xdElyd8vIHEMe7Sxb75GGs= X-Google-Smtp-Source: ALg8bN4b0daD6vxtcq7j+RUubc2fhqRNru6WzXY9GbcJs+lCMf/rPgWAHYA/xEr9vs9AR9f9KZ1Ssw== X-Received: by 2002:a1c:b14:: with SMTP id 20mr2189973wml.103.1548239303035; Wed, 23 Jan 2019 02:28:23 -0800 (PST) Received: from localhost (pD9E51040.dip0.t-ipconnect.de. [217.229.16.64]) by smtp.gmail.com with ESMTPSA id n15sm79643308wrt.21.2019.01.23.02.28.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 23 Jan 2019 02:28:22 -0800 (PST) From: Thierry Reding To: Greg Kroah-Hartman Cc: Jon Hunter , linux-serial@vger.kernel.org, linux-tegra@vger.kernel.org Subject: [PATCH v4 1/2] dt-bindings: serial: Add bindings for nvidia, tegra194-tcu Date: Wed, 23 Jan 2019 11:28:18 +0100 Message-Id: <20190123102819.29703-2-thierry.reding@gmail.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190123102819.29703-1-thierry.reding@gmail.com> References: <20190123102819.29703-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Mikko Perttunen Add bindings for the Tegra Combined UART device used to talk to the UART console on Tegra194 systems. Signed-off-by: Mikko Perttunen Reviewed-by: Rob Herring Acked-by: Jon Hunter Acked-by: Thierry Reding Signed-off-by: Thierry Reding --- .../bindings/serial/nvidia,tegra194-tcu.txt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt diff --git a/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt new file mode 100644 index 000000000000..085a8591accd --- /dev/null +++ b/Documentation/devicetree/bindings/serial/nvidia,tegra194-tcu.txt @@ -0,0 +1,35 @@ +NVIDIA Tegra Combined UART (TCU) + +The TCU is a system for sharing a hardware UART instance among multiple +systems within the Tegra SoC. It is implemented through a mailbox- +based protocol where each "virtual UART" has a pair of mailboxes, one +for transmitting and one for receiving, that is used to communicate +with the hardware implementing the TCU. + +Required properties: +- name : Should be tcu +- compatible + Array of strings + One of: + - "nvidia,tegra194-tcu" +- mbox-names: + "rx" - Mailbox for receiving data from hardware UART + "tx" - Mailbox for transmitting data to hardware UART +- mboxes: Mailboxes corresponding to the mbox-names. + +This node is a mailbox consumer. See the following files for details of +the mailbox subsystem, and the specifiers implemented by the relevant +provider(s): + +- .../mailbox/mailbox.txt +- .../mailbox/nvidia,tegra186-hsp.txt + +Example bindings: +----------------- + +tcu: tcu { + compatible = "nvidia,tegra194-tcu"; + mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_SM 0>, + <&hsp_aon TEGRA_HSP_MBOX_TYPE_SM 1>; + mbox-names = "rx", "tx"; +}; From patchwork Wed Jan 23 10:28:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1029865 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RMIduKsR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43l1hq71zCz9s4s for ; Wed, 23 Jan 2019 21:28:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726207AbfAWK21 (ORCPT ); Wed, 23 Jan 2019 05:28:27 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:39719 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726804AbfAWK21 (ORCPT ); Wed, 23 Jan 2019 05:28:27 -0500 Received: by mail-wr1-f67.google.com with SMTP id t27so1755224wra.6; Wed, 23 Jan 2019 02:28:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nZNXzqw8fCrReYPGYsgKzQdXXasNTfdH4AnKcSrRijo=; b=RMIduKsRl9yi/eCgXfZreI3lxRCHkt9uwCwE6cfXF5PnpyWwCJFarlTkLsTNkQdhV3 W9sl6vxMdll59WkrTdRUDL0qzK7qerligRv+ql6NiWKdqsQBX/tb1SXBW8mc6by6i1uR s+L4C+fjA7gLkQIYKJA85yhGRaFdzDFfhKoISWhRjRqaFkwZ1uQCZFaE7x/GAD3NasgL ktJE2jneBrBvo8LjEsd78kjPc9+L8iF4Ns2ibX7SVL4dbjVsGNKtqt8np4A7+5fliLr/ AC0Cs8z78mAHtVhLvfaKgBz91qVD/OlkE2dvtbdnNatUTjyI08x4MUZk3KBhW/ZByWzL WnbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nZNXzqw8fCrReYPGYsgKzQdXXasNTfdH4AnKcSrRijo=; b=YsThKQCA40bz31U97aVEEvu/MKJYq3yKcwAtGU+P5nEYKzfFslsK3HClCx5N3CoxbX AhdzYb4xJfvIOZcuWzZMA09W75CeNd6MuVIqGUswmJ5WaHtp6mT/6xDp8JOiG5MxA2AY 4hcqKX/4AO/6bFqe/iUHTlMpDzNdonnDljNFcav/K7eTHGH1BvVLh1sER+9m01LlScAp XKcpLIDQV8Q0PXurtknly921E206rzO4LxwtrpROVycbhGNTvVFULOKp4YdnU57Yk8BT +iJEVmyo0pKUDuF6MShX4rVYyfMWMWkaeHLIqL8nXlwhdPtcsqPzi5OqTOSRZLdqX49K gAIw== X-Gm-Message-State: AJcUukfI5/I0O6t7NPf+pERJNpJRvd+Zhnq/FE2iz0Cm6RsIMHxwpjVl evXdtM2Z2r4K09ChFNq1LhI= X-Google-Smtp-Source: ALg8bN7F8fbobZrYxpZELm3e2GsMIxY5zVDVPiSD0CJwpGcjYtmfDyXbf3iPDKumqETCev1J6cyUIQ== X-Received: by 2002:adf:b201:: with SMTP id u1mr1971689wra.165.1548239304445; Wed, 23 Jan 2019 02:28:24 -0800 (PST) Received: from localhost (pD9E51040.dip0.t-ipconnect.de. [217.229.16.64]) by smtp.gmail.com with ESMTPSA id n82sm54971191wma.42.2019.01.23.02.28.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 23 Jan 2019 02:28:23 -0800 (PST) From: Thierry Reding To: Greg Kroah-Hartman Cc: Jon Hunter , linux-serial@vger.kernel.org, linux-tegra@vger.kernel.org Subject: [PATCH v4 2/2] serial: Add Tegra Combined UART driver Date: Wed, 23 Jan 2019 11:28:19 +0100 Message-Id: <20190123102819.29703-3-thierry.reding@gmail.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190123102819.29703-1-thierry.reding@gmail.com> References: <20190123102819.29703-1-thierry.reding@gmail.com> MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org From: Thierry Reding The Tegra Combined UART (TCU) is a mailbox-based mechanism that allows multiplexing multiple "virtual UARTs" into a single hardware serial port. The TCU is the primary serial port on Tegra194 devices. Add a TCU driver utilizing the mailbox framework, as the used mailboxes are part of Tegra HSP blocks that are already controlled by the Tegra HSP mailbox driver. Based on work by Mikko Perttunen . Acked-by: Greg Kroah-Hartman Signed-off-by: Thierry Reding --- Changes in v4: - whitespace fixup Changes in v3: - explicitly flush mailbox to rate-limit console output drivers/tty/serial/Kconfig | 22 +++ drivers/tty/serial/Makefile | 1 + drivers/tty/serial/tegra-tcu.c | 298 +++++++++++++++++++++++++++++++ include/uapi/linux/serial_core.h | 3 + 4 files changed, 324 insertions(+) create mode 100644 drivers/tty/serial/tegra-tcu.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 089a6f285d5e..72966bc0ac76 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -335,6 +335,28 @@ config SERIAL_TEGRA are enabled). This driver uses the APB DMA to achieve higher baudrate and better performance. +config SERIAL_TEGRA_TCU + tristate "NVIDIA Tegra Combined UART" + depends on ARCH_TEGRA && TEGRA_HSP_MBOX + select SERIAL_CORE + help + Support for the mailbox-based TCU (Tegra Combined UART) serial port. + TCU is a virtual serial port that allows multiplexing multiple data + streams into a single hardware serial port. + +config SERIAL_TEGRA_TCU_CONSOLE + bool "Support for console on a Tegra TCU serial port" + depends on SERIAL_TEGRA_TCU=y + select SERIAL_CORE_CONSOLE + default y + ---help--- + If you say Y here, it will be possible to use a the Tegra TCU 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). + + If unsure, say Y. + config SERIAL_MAX3100 tristate "MAX3100 support" depends on SPI diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 1511e8a9f856..40b702aaa85e 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o +obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o obj-$(CONFIG_SERIAL_ARC) += arc_uart.o diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c new file mode 100644 index 000000000000..aaf8748a6147 --- /dev/null +++ b/drivers/tty/serial/tegra-tcu.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCU_MBOX_BYTE(i, x) ((x) << (i * 8)) +#define TCU_MBOX_BYTE_V(x, i) (((x) >> (i * 8)) & 0xff) +#define TCU_MBOX_NUM_BYTES(x) ((x) << 24) +#define TCU_MBOX_NUM_BYTES_V(x) (((x) >> 24) & 0x3) + +struct tegra_tcu { + struct uart_driver driver; +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) + struct console console; +#endif + struct uart_port port; + + struct mbox_client tx_client, rx_client; + struct mbox_chan *tx, *rx; +}; + +static unsigned int tegra_tcu_uart_tx_empty(struct uart_port *port) +{ + return TIOCSER_TEMT; +} + +static void tegra_tcu_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static unsigned int tegra_tcu_uart_get_mctrl(struct uart_port *port) +{ + return 0; +} + +static void tegra_tcu_uart_stop_tx(struct uart_port *port) +{ +} + +static void tegra_tcu_write_one(struct tegra_tcu *tcu, u32 value, + unsigned int count) +{ + void *msg; + + value |= TCU_MBOX_NUM_BYTES(count); + msg = (void *)(unsigned long)value; + mbox_send_message(tcu->tx, msg); + mbox_flush(tcu->tx, 1000); +} + +static void tegra_tcu_write(struct tegra_tcu *tcu, const char *s, + unsigned int count) +{ + unsigned int written = 0, i = 0; + bool insert_nl = false; + u32 value = 0; + + while (i < count) { + if (insert_nl) { + value |= TCU_MBOX_BYTE(written++, '\n'); + insert_nl = false; + i++; + } else if (s[i] == '\n') { + value |= TCU_MBOX_BYTE(written++, '\r'); + insert_nl = true; + } else { + value |= TCU_MBOX_BYTE(written++, s[i++]); + } + + if (written == 3) { + tegra_tcu_write_one(tcu, value, 3); + value = written = 0; + } + } + + if (written) + tegra_tcu_write_one(tcu, value, written); +} + +static void tegra_tcu_uart_start_tx(struct uart_port *port) +{ + struct tegra_tcu *tcu = port->private_data; + struct circ_buf *xmit = &port->state->xmit; + unsigned long count; + + for (;;) { + count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + if (!count) + break; + + tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count); + xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); + } + + uart_write_wakeup(port); +} + +static void tegra_tcu_uart_stop_rx(struct uart_port *port) +{ +} + +static void tegra_tcu_uart_break_ctl(struct uart_port *port, int ctl) +{ +} + +static int tegra_tcu_uart_startup(struct uart_port *port) +{ + return 0; +} + +static void tegra_tcu_uart_shutdown(struct uart_port *port) +{ +} + +static void tegra_tcu_uart_set_termios(struct uart_port *port, + struct ktermios *new, + struct ktermios *old) +{ +} + +static const struct uart_ops tegra_tcu_uart_ops = { + .tx_empty = tegra_tcu_uart_tx_empty, + .set_mctrl = tegra_tcu_uart_set_mctrl, + .get_mctrl = tegra_tcu_uart_get_mctrl, + .stop_tx = tegra_tcu_uart_stop_tx, + .start_tx = tegra_tcu_uart_start_tx, + .stop_rx = tegra_tcu_uart_stop_rx, + .break_ctl = tegra_tcu_uart_break_ctl, + .startup = tegra_tcu_uart_startup, + .shutdown = tegra_tcu_uart_shutdown, + .set_termios = tegra_tcu_uart_set_termios, +}; + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) +static void tegra_tcu_console_write(struct console *cons, const char *s, + unsigned int count) +{ + struct tegra_tcu *tcu = container_of(cons, struct tegra_tcu, console); + + tegra_tcu_write(tcu, s, count); +} + +static int tegra_tcu_console_setup(struct console *cons, char *options) +{ + return 0; +} +#endif + +static void tegra_tcu_receive(struct mbox_client *cl, void *msg) +{ + struct tegra_tcu *tcu = container_of(cl, struct tegra_tcu, rx_client); + struct tty_port *port = &tcu->port.state->port; + u32 value = (u32)(unsigned long)msg; + unsigned int num_bytes, i; + + num_bytes = TCU_MBOX_NUM_BYTES_V(value); + + for (i = 0; i < num_bytes; i++) + tty_insert_flip_char(port, TCU_MBOX_BYTE_V(value, i), + TTY_NORMAL); + + tty_flip_buffer_push(port); +} + +static int tegra_tcu_probe(struct platform_device *pdev) +{ + struct uart_port *port; + struct tegra_tcu *tcu; + int err; + + tcu = devm_kzalloc(&pdev->dev, sizeof(*tcu), GFP_KERNEL); + if (!tcu) + return -ENOMEM; + + tcu->tx_client.dev = &pdev->dev; + tcu->rx_client.dev = &pdev->dev; + tcu->rx_client.rx_callback = tegra_tcu_receive; + + tcu->tx = mbox_request_channel_byname(&tcu->tx_client, "tx"); + if (IS_ERR(tcu->tx)) { + err = PTR_ERR(tcu->tx); + dev_err(&pdev->dev, "failed to get tx mailbox: %d\n", err); + return err; + } + + tcu->rx = mbox_request_channel_byname(&tcu->rx_client, "rx"); + if (IS_ERR(tcu->rx)) { + err = PTR_ERR(tcu->rx); + dev_err(&pdev->dev, "failed to get rx mailbox: %d\n", err); + goto free_tx; + } + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) + /* setup the console */ + strcpy(tcu->console.name, "ttyTCU"); + tcu->console.device = uart_console_device; + tcu->console.flags = CON_PRINTBUFFER | CON_ANYTIME; + tcu->console.index = -1; + tcu->console.write = tegra_tcu_console_write; + tcu->console.setup = tegra_tcu_console_setup; + tcu->console.data = &tcu->driver; +#endif + + /* setup the driver */ + tcu->driver.owner = THIS_MODULE; + tcu->driver.driver_name = "tegra-tcu"; + tcu->driver.dev_name = "ttyTCU"; +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) + tcu->driver.cons = &tcu->console; +#endif + tcu->driver.nr = 1; + + err = uart_register_driver(&tcu->driver); + if (err) { + dev_err(&pdev->dev, "failed to register UART driver: %d\n", + err); + goto free_rx; + } + + /* setup the port */ + port = &tcu->port; + spin_lock_init(&port->lock); + port->dev = &pdev->dev; + port->type = PORT_TEGRA_TCU; + port->ops = &tegra_tcu_uart_ops; + port->fifosize = 1; + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->private_data = tcu; + + err = uart_add_one_port(&tcu->driver, port); + if (err) { + dev_err(&pdev->dev, "failed to add UART port: %d\n", err); + goto unregister_uart; + } + + platform_set_drvdata(pdev, tcu); +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) + register_console(&tcu->console); +#endif + + return 0; + +unregister_uart: + uart_unregister_driver(&tcu->driver); +free_rx: + mbox_free_channel(tcu->rx); +free_tx: + mbox_free_channel(tcu->tx); + + return err; +} + +static int tegra_tcu_remove(struct platform_device *pdev) +{ + struct tegra_tcu *tcu = platform_get_drvdata(pdev); + +#if IS_ENABLED(CONFIG_SERIAL_TEGRA_TCU_CONSOLE) + unregister_console(&tcu->console); +#endif + uart_remove_one_port(&tcu->driver, &tcu->port); + uart_unregister_driver(&tcu->driver); + mbox_free_channel(tcu->rx); + mbox_free_channel(tcu->tx); + + return 0; +} + +static const struct of_device_id tegra_tcu_match[] = { + { .compatible = "nvidia,tegra194-tcu" }, + { } +}; + +static struct platform_driver tegra_tcu_driver = { + .driver = { + .name = "tegra-tcu", + .of_match_table = tegra_tcu_match, + }, + .probe = tegra_tcu_probe, + .remove = tegra_tcu_remove, +}; +module_platform_driver(tegra_tcu_driver); + +MODULE_AUTHOR("Mikko Perttunen "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("NVIDIA Tegra Combined UART driver"); diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index df4a7534e239..6009ee2c2e99 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -79,6 +79,9 @@ /* Nuvoton UART */ #define PORT_NPCM 40 +/* NVIDIA Tegra Combined UART */ +#define PORT_TEGRA_TCU 41 + /* Intel EG20 */ #define PORT_PCH_8LINE 44 #define PORT_PCH_2LINE 45