From patchwork Mon Mar 20 08:11:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaWei Wang X-Patchwork-Id: 13181503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E0760C76195 for ; Mon, 20 Mar 2023 15:48:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9fWkh/s9z5xPSjvJK5BFq1mc6JTmwlJ1DUBMOcajhKo=; b=5BZZy8YGRM+12j CDn8X9dnS0EMBHx6y7uqNP9WpPomvox1lO3UaCUhkgKH7TpOvlsEF+74eOmjcEd6t9MvuKS5da48L OEQZj7Kn+lQ3WmfOU4057zeX/j0nOYSN0yv9n7GBcI1vOC5L+BEuu780iQUaMFu50XxlTLtm6YaFi wbSv0Gef7SyWi+dNu/fWHuUqwI0FJ9g54HvHIthAjD43lKj5O7hEhmvw0Sd1s5QIro0X7un4YD2I2 dGb+3KbMUzvtXcb4v+WnGYXUVwuLOoLvJ5XBuSbSgFcG6qXFYtJbnOFDTSKUPdQmy1DOvCGIrdMYw punsG+dGI1UzXzOO2KWA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1peHjb-009ciM-23; Mon, 20 Mar 2023 15:47:43 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1peHjU-009cgQ-2p for linux-arm-kernel@bombadil.infradead.org; Mon, 20 Mar 2023 15:47:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Content-Transfer-Encoding :MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description; bh=YKBivxmarRwTpeg43hQochiZ5/lNJ3JG8dlYrjKSvho=; b=kxocZCVrdQIxk2OCHEgLkUU55z uzmNWmqZoRL2/E08oMylipLzt2lS8H3XKL+1XtI0VIw2Kd3VlXp+aZFyo45IHE4Gr4586C2M8EZLU 0M50ojHN6rjC1rJGNi9uqXzj5ZIjoMDGWejZE5SQBLBa8GeTwUSUwga0zsU/PJvNA3l0IqYLDQkzf OHBVvZt4Mf4Z1dXhAnmfwP6mPrQwCIIFENhSdWASDIqOZfer8wBmq3Ze/D4ktX7RFqXixElN6PS9K t6Q571ADg2Lf+IAbsztco+SWt6zLjmbBB4c6Y6laZtliJVF23XW0DhASPNXUZvGt96laR25f8UA4n hI377yyw==; Received: from twspam01.aspeedtech.com ([211.20.114.71]) by desiato.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1peAdC-003rLB-2o for linux-arm-kernel@lists.infradead.org; Mon, 20 Mar 2023 08:12:50 +0000 Received: from mail.aspeedtech.com ([192.168.0.24]) by twspam01.aspeedtech.com with ESMTP id 32K7v6wi088828; Mon, 20 Mar 2023 15:57:06 +0800 (GMT-8) (envelope-from chiawei_wang@aspeedtech.com) Received: from Chiawei-PC03.aspeed.com (192.168.2.66) by TWMBX02.aspeed.com (192.168.0.24) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 20 Mar 2023 16:11:39 +0800 From: Chia-Wei Wang To: , , , , , , , , , , , , , , , , Subject: [PATCH v3 4/5] serial: 8250: Add AST2600 UART driver Date: Mon, 20 Mar 2023 16:11:32 +0800 Message-ID: <20230320081133.23655-5-chiawei_wang@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230320081133.23655-1-chiawei_wang@aspeedtech.com> References: <20230320081133.23655-1-chiawei_wang@aspeedtech.com> MIME-Version: 1.0 X-Originating-IP: [192.168.2.66] X-ClientProxiedBy: TWMBX02.aspeed.com (192.168.0.24) To TWMBX02.aspeed.com (192.168.0.24) X-DNSRBL: X-MAIL: twspam01.aspeedtech.com 32K7v6wi088828 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230320_081239_701567_A52574AA X-CRM114-Status: GOOD ( 25.35 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add new UART driver with DMA support for Aspeed AST2600 SoCs. The drivers mainly prepare the dma instance based on the 8250_dma implementation to leverage the AST2600 UART DMA (UDMA) engine. Signed-off-by: Chia-Wei Wang --- drivers/tty/serial/8250/8250_aspeed.c | 224 ++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 8 + drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 233 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_aspeed.c diff --git a/drivers/tty/serial/8250/8250_aspeed.c b/drivers/tty/serial/8250/8250_aspeed.c new file mode 100644 index 000000000000..04d0bf6fba28 --- /dev/null +++ b/drivers/tty/serial/8250/8250_aspeed.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) ASPEED Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "8250.h" + +#define DEVICE_NAME "aspeed-uart" + +struct ast8250_data { + int line; + int irq; + u8 __iomem *regs; + struct reset_control *rst; + struct clk *clk; +#ifdef CONFIG_SERIAL_8250_DMA + struct uart_8250_dma dma; +#endif +}; + +#ifdef CONFIG_SERIAL_8250_DMA +static int ast8250_rx_dma(struct uart_8250_port *p); + +static void ast8250_rx_dma_complete(void *param) +{ + struct uart_8250_port *p = param; + struct uart_8250_dma *dma = p->dma; + struct tty_port *tty_port = &p->port.state->port; + struct dma_tx_state state; + int count; + + dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + + count = dma->rx_size - state.residue; + + tty_insert_flip_string(tty_port, dma->rx_buf, count); + p->port.icount.rx += count; + + tty_flip_buffer_push(tty_port); + + ast8250_rx_dma(p); +} + +static int ast8250_rx_dma(struct uart_8250_port *p) +{ + struct uart_8250_dma *dma = p->dma; + struct dma_async_tx_descriptor *tx; + + tx = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, + dma->rx_size, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx) + return -EBUSY; + + tx->callback = ast8250_rx_dma_complete; + tx->callback_param = p; + + dma->rx_cookie = dmaengine_submit(tx); + + dma_async_issue_pending(dma->rxchan); + + return 0; +} +#endif + +static int ast8250_handle_irq(struct uart_port *port) +{ + return serial8250_handle_irq(port, serial_port_in(port, UART_IIR)); +} + +static int ast8250_startup(struct uart_port *port) +{ +#ifdef CONFIG_SERIAL_8250_DMA + int rc; + struct uart_8250_port *up = up_to_u8250p(port); + + rc = serial8250_do_startup(port); + if (rc) + return rc; + + /* + * The default RX DMA is launched upon rising DR bit. + * + * However, this can result in byte lost if UART FIFO has + * been overruned before the DMA engine gets prepared and + * read the data out. This is especially common when UART + * DMA is used for file transfer. Thus we initiate RX DMA + * as early as possible. + */ + if (up->dma) + return ast8250_rx_dma(up); + + return 0; +#else + return serial8250_do_startup(port); +#endif +} + +static void ast8250_shutdown(struct uart_port *port) +{ + return serial8250_do_shutdown(port); +} + +static int ast8250_probe(struct platform_device *pdev) +{ + int rc; + struct uart_8250_port uart = {}; + struct uart_port *port = &uart.port; + struct device *dev = &pdev->dev; + struct ast8250_data *data; + struct resource *res; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) + return data->irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(dev, "failed to get register base\n"); + return -ENODEV; + } + + data->regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to map registers\n"); + return PTR_ERR(data->regs); + } + + data->clk = devm_clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + dev_err(dev, "failed to get clocks\n"); + return -ENODEV; + } + + rc = clk_prepare_enable(data->clk); + if (rc) { + dev_err(dev, "failed to enable clock\n"); + return rc; + } + + data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); + if (!IS_ERR(data->rst)) + reset_control_deassert(data->rst); + + spin_lock_init(&port->lock); + port->dev = dev; + port->type = PORT_16550A; + port->irq = data->irq; + port->line = of_alias_get_id(dev->of_node, "serial"); + port->handle_irq = ast8250_handle_irq; + port->mapbase = res->start; + port->mapsize = resource_size(res); + port->membase = data->regs; + port->uartclk = clk_get_rate(data->clk); + port->regshift = 2; + port->iotype = UPIO_MEM32; + port->flags = UPF_FIXED_TYPE | UPF_FIXED_PORT | UPF_SHARE_IRQ; + port->startup = ast8250_startup; + port->shutdown = ast8250_shutdown; + port->private_data = data; +#ifdef CONFIG_SERIAL_8250_DMA + data->dma.rxconf.src_maxburst = UART_XMIT_SIZE; + data->dma.txconf.dst_maxburst = UART_XMIT_SIZE; + uart.dma = &data->dma; +#endif + + data->line = serial8250_register_8250_port(&uart); + if (data->line < 0) { + dev_err(dev, "failed to register 8250 port\n"); + return data->line; + } + + platform_set_drvdata(pdev, data); + + return 0; +} + +static int ast8250_remove(struct platform_device *pdev) +{ + struct ast8250_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + + return 0; +} + +static const struct of_device_id ast8250_of_match[] = { + { .compatible = "aspeed,ast2600-uart" }, + { }, +}; + +static struct platform_driver ast8250_platform_driver = { + .driver = { + .name = DEVICE_NAME, + .of_match_table = ast8250_of_match, + }, + .probe = ast8250_probe, + .remove = ast8250_remove, +}; + +module_platform_driver(ast8250_platform_driver); + +MODULE_AUTHOR("Chia-Wei Wang "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Aspeed 8250 UART Driver with DMA support"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 978dc196c29b..f8a2231816c4 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -253,6 +253,14 @@ config SERIAL_8250_ACCENT To compile this driver as a module, choose M here: the module will be called 8250_accent. +config SERIAL_8250_ASPEED + tristate "Aspeed UART" + depends on ARCH_ASPEED && SERIAL_8250 + help + If you have a system using an Aspeed AST26xx SoCs and wish to + make use of its 16550A-compatible UART devices with DMA support, + say Y to this option. If unsure, say N. + config SERIAL_8250_ASPEED_VUART tristate "Aspeed Virtual UART" depends on SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 4fc2fc1f41b6..7b959e652b67 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o +obj-$(CONFIG_SERIAL_8250_ASPEED) += 8250_aspeed.o obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o