From patchwork Fri Jul 26 13:27:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sudheer v X-Patchwork-Id: 1138759 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45yN8J6t1lz9s00 for ; Tue, 30 Jul 2019 13:58:40 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="OimnIgtt"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 45yN8J5qZYzDqNS for ; Tue, 30 Jul 2019 13:58:40 +1000 (AEST) X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::543; helo=mail-pg1-x543.google.com; envelope-from=open.sudheer@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="OimnIgtt"; dkim-atps=neutral Received: from mail-pg1-x543.google.com (mail-pg1-x543.google.com [IPv6:2607:f8b0:4864:20::543]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 45w8wB6ZrMzDqQG for ; Fri, 26 Jul 2019 23:25:30 +1000 (AEST) Received: by mail-pg1-x543.google.com with SMTP id u17so24797504pgi.6 for ; Fri, 26 Jul 2019 06:25:30 -0700 (PDT) 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; bh=HsYjZwlw1bDW7WLit2YsMYvuhA43PKhD+T+wE/OMNmc=; b=OimnIgttqlsyl0kVjbVv8LUU1TN1IfN8SUDbK9+zJH3tPmYvzIVA5JSCTyjrAp8gNi KWuHGwjOkrPipddb8DOhTKp93CE4BqZkvaTgSoXdLjfdbuWo+h/nV5XPXjzveKLTGTdz NVlZd4jM9CPKIS9Xk/XHEoi9oQcENBQZscXadJbl77AjnGl0tfjUuMeHc4OT/kSDGRrz Ix3uLqARpkDfcdiZFfSf/Y23TwCpddg5yowWBn59HzrOfIDrGK136+WLc/Usg1eM2kWM hjUbj/k+ihUEzdAn4kHecPAkb4J/uL6ZIUtyXlOFYXTbJD8MqkHDkyX7KMrH1jduR0U6 fEiA== 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; bh=HsYjZwlw1bDW7WLit2YsMYvuhA43PKhD+T+wE/OMNmc=; b=YRIMJ8gxcrXHFNsjl/D/GjlTN50yMayG1D8gunLjMSBv2CEm8wE0NzLqUw9FXFALte E6A1bIac5Rf6GCJir9GViVZpYSj7a8J/2ZN/bmt9DmnwUNi8B0dX9rSthaszvl/4p/Dp SwPaf/dC6IzLr3Tw1KsroXgu+CK3nERywMLNVBvc2FCR9mZcClgI9P79QALCAtM2vcAb qFuHYxxkZqqZFyGTcJ4xPHZrgvyFAS4gyVURkHQNBBcszJ6MZqbmDR7ffBcLS9By5nRl uYpnPc1p2IeL0sDIUGHvA2ZiEsPR0n6CGNEgqEdC7Swwwl5+bqdLA6amBBmGXvGvRQLA 5eeg== X-Gm-Message-State: APjAAAWyG9z4zrQUxNELGo5ojqWkrpKqFKEddYc/mP+22MiWJXiGziy8 BxCv1aQbXNrDIbWI9Qi4ls4= X-Google-Smtp-Source: APXvYqw2jhxzXnIO56KRmXsy0Jcucypc/8ctm4oOK6PPSRmHHrEPv/gRNFZmsi8GqVJB0ah8+lcmaQ== X-Received: by 2002:a62:2d3:: with SMTP id 202mr22576628pfc.131.1564147527379; Fri, 26 Jul 2019 06:25:27 -0700 (PDT) Received: from Pilot130.192.168.0.22 (211-20-114-70.HINET-IP.hinet.net. [211.20.114.70]) by smtp.googlemail.com with ESMTPSA id k36sm54544603pgl.42.2019.07.26.06.25.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jul 2019 06:25:26 -0700 (PDT) From: "sudheer.v" To: gregkh@linuxfoundation.org, jslaby@suse.com, joel@jms.id.au, andrew@aj.id.au, benh@kernel.crashing.org, robh+dt@kernel.org, mark.rutland@arm.com, shivahshankar.shankarnarayanrao@aspeedtech.com, sudheer.veliseti@aspeedtech.com Subject: [patch v4 1/5] AST2500 DMA UART driver Date: Fri, 26 Jul 2019 18:57:16 +0530 Message-Id: <1564147640-30753-2-git-send-email-open.sudheer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> References: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> X-Mailman-Approved-At: Tue, 30 Jul 2019 13:58:37 +1000 X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, sudheer veliseti Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" From: sudheer veliseti UART driver for Aspeed's bmc chip AST2500 Design approch: AST2500 has dedicated Uart DMA controller which has 12 sets of Tx and RX channels connected to UART controller directly. Since the DMA controller have dedicated buffers and registers, there would be little benifit in adding DMA framework overhead. So the software for DMA controller is included within the UART driver itself. implementation details: 'struct ast_uart_port' is populated and registered with uart_core. code is organised into two layers UART-layer and DMA-Layer,both of them are in the same file.UART-layer requests Rx and Tx dma channels and registers callbacks with DMA controller software Layer Interrupt service routine for DMA controller is the crucial one for Handling all the tx and rx data. ISRs installed for individual uarts are just dummy,and are helpful only to report any spurious interrupts in hardware. Signed-off-by: sudheer veliseti --- Changes from v3->v4: - per port uart structures are registerd directly with uart core Instead of registering through 8250 Frame work, ast_uart_port is registered using uart_add_one_port -SDMA_RX_FIX macro replaced with CONFIG_AST_UART_DMA_RX_INTERRUPT -ast_uart_sdma_isr : DMA interrupt handler code is improvised -replaced pr_debug with ftrace wherever appropriate -dev_err is used in all error return cases -uart driver structure ast25xx_uart_reg is modified -driver name changed to ast2500-uart-dma-drv -rx_timer initialisation and callback fn modified Changes from v2->v3: -custom debug replaced by in kerenl dynamic debug: pr_debug -change-logs added .../tty/serial/8250/8250_ast2500_uart_dma.c | 1901 +++++++++++++++++ 1 file changed, 1901 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_ast2500_uart_dma.c diff --git a/drivers/tty/serial/8250/8250_ast2500_uart_dma.c b/drivers/tty/serial/8250/8250_ast2500_uart_dma.c new file mode 100644 index 000000000000..bc830d605372 --- /dev/null +++ b/drivers/tty/serial/8250/8250_ast2500_uart_dma.c @@ -0,0 +1,1901 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DMA UART Driver for ASPEED BMC chip: AST2500 + * + * Copyright (C) 2019 sudheer Kumar veliseti, Aspeed technology Inc. + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "8250.h" + +#define SERIAL8250_CONSOLE NULL +#define TTY_AST_MAJOR 204 +#define TTY_AST_MINOR 68 + +#define DMA_BUFF_SIZE 0x1000 +#define SDMA_RX_BUFF_SIZE 0x10000 +#define PASS_LIMIT 256 +#define UART_DMA_NR CONFIG_AST_NR_DMA_UARTS +#define AST_UART_SDMA_CH 12 + +/* enum ast_uart_chan_op + * operation codes passed to the DMA code by the user, and also used + * to inform the current channel owner of any changes to the system state + */ +enum ast_uart_chan_op { + AST_UART_DMAOP_TRIGGER, + AST_UART_DMAOP_STOP, + AST_UART_DMAOP_PAUSE, +}; + +/* ast_uart_dma_cbfn: buffer callback routinei type */ +typedef void (*ast_uart_dma_cbfn)(void *dev_id, u16 len); + +struct ast_sdma_info { + u8 ch_no; + u8 direction; + u8 enable; + void *priv; + char *sdma_virt_addr; + dma_addr_t dma_phy_addr; + /* cdriver callbacks */ + ast_uart_dma_cbfn callback_fn; /* buffer done callback */ +}; + +struct ast_sdma_ch { + struct ast_sdma_info tx_dma_info[AST_UART_SDMA_CH]; + struct ast_sdma_info rx_dma_info[AST_UART_SDMA_CH]; +}; + +struct ast_sdma { + void __iomem *reg_base; + int dma_irq; + struct ast_sdma_ch *dma_ch; + struct regmap *map; +}; + +#define UART_TX_SDMA_EN 0x00 +#define UART_RX_SDMA_EN 0x04 +#define UART_SDMA_CONF 0x08 /* Misc, Buffer size */ +#define UART_SDMA_TIMER 0x0C +#define UART_TX_SDMA_REST 0x20 +#define UART_RX_SDMA_REST 0x24 +#define UART_TX_SDMA_IER 0x30 +#define UART_TX_SDMA_ISR 0x34 +#define UART_RX_SDMA_IER 0x38 +#define UART_RX_SDMA_ISR 0x3C +#define UART_TX_R_POINT(x) (0x40 + ((x) * 0x20)) +#define UART_TX_W_POINT(x) (0x44 + ((x) * 0x20)) +#define UART_TX_SDMA_ADDR(x) (0x48 + ((x) * 0x20)) +#define UART_RX_R_POINT(x) (0x50 + ((x) * 0x20)) +#define UART_RX_W_POINT(x) (0x54 + ((x) * 0x20)) +#define UART_RX_SDMA_ADDR(x) (0x58 + ((x) * 0x20)) +#define SDMA_CH_EN(x) BIT(x) + +#define SDMA_TX_BUFF_SIZE_MASK (0x3) +#define SDMA_SET_TX_BUFF_SIZE(x)(x) +#define SDMA_BUFF_SIZE_1KB (0x0) +#define SDMA_BUFF_SIZE_4KB (0x1) +#define SDMA_BUFF_SIZE_16KB (0x2) +#define SDMA_BUFF_SIZE_64KB (0x3) +#define SDMA_RX_BUFF_SIZE_MASK (0x3 << 2) +#define SDMA_SET_RX_BUFF_SIZE(x)((x) << 2) +#define SDMA_TIMEOUT_DIS BIT(4) + +#define UART_SDMA11_INT BIT(11) +#define UART_SDMA10_INT BIT(10) +#define UART_SDMA9_INT BIT(9) +#define UART_SDMA8_INT BIT(8) +#define UART_SDMA7_INT BIT(7) +#define UART_SDMA6_INT BIT(6) +#define UART_SDMA5_INT BIT(5) +#define UART_SDMA4_INT BIT(4) +#define UART_SDMA3_INT BIT(3) +#define UART_SDMA2_INT BIT(2) +#define UART_SDMA1_INT BIT(1) +#define UART_SDMA0_INT BIT(0) + +/* + * Configuration: + * share_irqs - whether we pass IRQF_SHARED to request_irq(). + * This option is unsafe when used on edge-triggered interrupts. + */ +static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; + +static unsigned int nr_uarts = CONFIG_AST_RUNTIME_DMA_UARTS; + +struct ast_uart_port { + struct uart_port port; + unsigned short capabilities; /* port capabilities */ + unsigned short bugs; /* port bugs */ + unsigned int tx_loadsz; /* transmit fifo load size */ + unsigned char acr; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned char mcr_mask; /* mask of user bits */ + unsigned char mcr_force; /* mask of forced bits */ + struct circ_buf rx_dma_buf; + struct circ_buf tx_dma_buf; + unsigned char dma_channel; + dma_addr_t dma_rx_addr; /* Mapped ADMA descr. table */ + dma_addr_t dma_tx_addr; /* Mapped ADMA descr. table */ +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT + struct tasklet_struct rx_tasklet; +#else + struct timer_list rx_timer; + unsigned int workaround; +#endif + struct tasklet_struct tx_tasklet; + spinlock_t lock; + int tx_done; + int tx_count; + struct platform_device *ast_uart_pdev; +/* + * Some bits in registers are cleared on a read, so they must + * be saved whenever the register is read but the bits will not + * be immediately processed. + */ +#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS + unsigned char lsr_saved_flags; +#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA + unsigned char msr_saved_flags; + + /* + * We provide a per-port pm hook. + */ + void (*pm)(struct uart_port *port, unsigned int state, + unsigned int old); +}; + +static struct ast_uart_port ast_uart_ports[UART_DMA_NR]; + +#define GET_DEV(ast_uart_port_priv_ptr)\ + (ast_uart_port_priv_ptr->ast_uart_pdev->dev) + +static inline struct ast_uart_port * +to_ast_dma_uart_port(struct uart_port *uart) { + return container_of(uart, struct ast_uart_port, port); +} + +struct irq_info { + spinlock_t lock; + struct ast_uart_port *up; +}; + +static struct irq_info ast_uart_irq[1]; +static DEFINE_MUTEX(ast_uart_mutex); + +/* + * Here we define the default xmit fifo size used for each type of UART. + */ +static const struct serial8250_config uart_config[] = { + [PORT_UNKNOWN] = { + .name = "unknown", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_8250] = { + .name = "8250", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16450] = { + .name = "16450", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550] = { + .name = "16550", + .fifo_size = 1, + .tx_loadsz = 1, + }, + [PORT_16550A] = { + .name = "16550A", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 + | UART_FCR_DMA_SELECT, + .flags = UART_CAP_FIFO, + }, +}; + +#define map_8250_reg_offset(up, offset) ((offset) << (up->port.regshift)) + + + +// SDMA - software Layer : ast-uart-sdma.c +static inline void ast_uart_sdma_write(struct ast_sdma *sdma, + u32 val, u32 reg) +{ + trace_printk("uart dma-write : val: %x, reg: %x\n", val, reg); + writel(val, sdma->reg_base + reg); +} + +static inline u32 ast_uart_sdma_read(struct ast_sdma *sdma, u32 reg) +{ + return readl(sdma->reg_base + reg); +} + +struct ast_sdma ast_uart_sdma; + +int ast_uart_tx_sdma_enqueue(u8 ch, dma_addr_t tx_buff) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + + trace_printk("ch = %d, tx buff = %x\n", ch, tx_buff); + local_irq_save(flags); + ast_uart_sdma_write(sdma, tx_buff, UART_TX_SDMA_ADDR(ch)); + local_irq_restore(flags); + + return 0; +} + +void ast_uart_set_sdma_time_out(u16 val) +{ + struct ast_sdma *sdma = &ast_uart_sdma; + + ast_uart_sdma_write(sdma, val, UART_SDMA_TIMER); +} + +int ast_uart_rx_sdma_ctrl(u8 ch, enum ast_uart_chan_op op) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]); + + local_irq_save(flags); + trace_printk("ch=%d op=%d\n", ch, op); + switch (op) { + case AST_UART_DMAOP_TRIGGER: + dma_ch->enable = 1; +#ifndef CONFIG_AST_UART_DMA_RX_INTERRUPT + ast_uart_set_sdma_time_out(0xffff); +#endif + // set enable + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) | (0x1 << ch), + UART_RX_SDMA_EN); + break; + case AST_UART_DMAOP_STOP: + // disable engine + dma_ch->enable = 0; + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) + & ~(0x1 << ch), UART_RX_SDMA_EN); + // set reset + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_REST) | + (0x1 << ch), UART_RX_SDMA_REST); + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_REST) & + ~(0x1 << ch), UART_RX_SDMA_REST); + + ast_uart_sdma_write(sdma, 0, UART_RX_R_POINT(ch)); + ast_uart_sdma_write(sdma, + dma_ch->dma_phy_addr, UART_RX_SDMA_ADDR(ch)); + break; + case AST_UART_DMAOP_PAUSE: + // disable engine + dma_ch->enable = 0; + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) & + ~(0x1 << ch), UART_RX_SDMA_EN); + break; + } + + local_irq_restore(flags); + return 0; +} + +int ast_uart_tx_sdma_ctrl(u8 ch, enum ast_uart_chan_op op) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + struct ast_sdma_info *dma_ch = &(sdma->dma_ch->tx_dma_info[ch]); + + trace_printk("ch=%d op=%d\n", ch, op); + local_irq_save(flags); + switch (op) { + case AST_UART_DMAOP_TRIGGER: + dma_ch->enable = 1; + // set enable + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) | (0x1 << ch), + UART_TX_SDMA_EN); + break; + case AST_UART_DMAOP_STOP: + dma_ch->enable = 0; + // disable engine + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) + & ~(0x1 << ch), UART_TX_SDMA_EN); + // set reset + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_REST) + | (0x1 << ch), UART_TX_SDMA_REST); + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_REST) + & ~(0x1 << ch), UART_TX_SDMA_REST); + + ast_uart_sdma_write(sdma, 0, UART_TX_W_POINT(ch)); + break; + case AST_UART_DMAOP_PAUSE: + dma_ch->enable = 0; + // disable engine + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) + & ~(0x1 << ch), UART_TX_SDMA_EN); + } + + local_irq_restore(flags); + return 0; +} + +u32 ast_uart_get_tx_sdma_pt(u8 ch) +{ + struct ast_sdma *sdma = &ast_uart_sdma; + + return ast_uart_sdma_read(sdma, UART_TX_R_POINT(ch)); +} + +int ast_uart_tx_sdma_update(u8 ch, u16 point) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + + trace_printk("TX DMA CTRL [ch %d] point %d\n", ch, point); + local_irq_save(flags); + ast_uart_sdma_write(sdma, point, UART_TX_W_POINT(ch)); + local_irq_restore(flags); + return 0; +} + +int ast_uart_tx_sdma_request(u8 ch, ast_uart_dma_cbfn rtn, void *id) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + struct ast_sdma_info *dma_ch = &(sdma->dma_ch->tx_dma_info[ch]); + + trace_printk("TX DMA REQUEST ch = %d\n", ch); + local_irq_save(flags); + if (dma_ch->enable) { + local_irq_restore(flags); + return -EBUSY; + } + dma_ch->priv = id; + dma_ch->callback_fn = rtn; + + // DMA IRQ En + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_IER) | (1 << ch), + UART_TX_SDMA_IER); + + local_irq_restore(flags); + + return 0; +} + +int ast_uart_rx_sdma_update(u8 ch, u16 point) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + + trace_printk("RX DMA CTRL [ch %d] point %x\n", ch, point); + local_irq_save(flags); + ast_uart_sdma_write(sdma, point, UART_RX_R_POINT(ch)); + local_irq_restore(flags); + return 0; +} + +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT +char *ast_uart_rx_sdma_request(u8 ch, ast_uart_dma_cbfn rtn, void *id) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]); + + trace_printk("RX DMA REQUEST ch = %d\n", ch); + local_irq_save(flags); + + if (dma_ch->enable) { + local_irq_restore(flags); + return 0; + } + dma_ch->priv = id; + dma_ch->callback_fn = rtn; + // DMA IRQ En + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_IER) | (1 << ch), + UART_RX_SDMA_IER); + + local_irq_restore(flags); + + return dma_ch->sdma_virt_addr; +} + +#else +char *ast_uart_rx_sdma_request(u8 ch, void *id) +{ + unsigned long flags; + struct ast_sdma *sdma = &ast_uart_sdma; + struct ast_sdma_info *dma_ch = &(sdma->dma_ch->rx_dma_info[ch]); + + trace_printk("RX DMA REQUEST ch = %d\n", ch); + + local_irq_save(flags); + + if (dma_ch->enable) { + local_irq_restore(flags); + return ERR_PTR(-EBUSY); + } + dma_ch->priv = id; + + local_irq_restore(flags); + return dma_ch->sdma_virt_addr; +} +#endif + +u16 ast_uart_get_rx_sdma_pt(u8 ch) +{ + struct ast_sdma *sdma = &ast_uart_sdma; + + return ast_uart_sdma_read(sdma, UART_RX_W_POINT(ch)); +} + +static inline void ast_sdma_bufffdone(struct ast_sdma_info *sdma_ch) +{ + u32 len; + struct ast_sdma *sdma = &ast_uart_sdma; + + if (sdma_ch->enable == 0) { + pr_debug("sdma Please check ch_no %x %s!!!!!\n", + sdma_ch->ch_no, sdma_ch->direction ? "TX" : "RX"); + if (sdma_ch->direction) { + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_TX_SDMA_EN) + & ~(0x1 << sdma_ch->ch_no), UART_TX_SDMA_EN); + } else { + ast_uart_sdma_write(sdma, + ast_uart_sdma_read(sdma, UART_RX_SDMA_EN) & + ~(0x1 << sdma_ch->ch_no), UART_RX_SDMA_EN); + ast_uart_rx_sdma_update(sdma_ch->ch_no, + ast_uart_get_rx_sdma_pt(sdma_ch->ch_no)); + trace_printk("OFFSET : UART_RX_SDMA_EN = %x\n ", + ast_uart_sdma_read(sdma, UART_RX_SDMA_EN)); + } + return; + } + + if (sdma_ch->direction) { + len = ast_uart_sdma_read(sdma, UART_TX_R_POINT(sdma_ch->ch_no)); + trace_printk("tx rp %x , wp %x\n", + ast_uart_sdma_read(sdma, UART_TX_R_POINT(sdma_ch->ch_no)), + ast_uart_sdma_read(sdma, UART_TX_W_POINT(sdma_ch->ch_no)) + ); + } else { + trace_printk("rx rp %x , wp %x\n", + ast_uart_sdma_read(sdma, UART_RX_R_POINT(sdma_ch->ch_no)), + ast_uart_sdma_read(sdma, UART_RX_W_POINT(sdma_ch->ch_no)) + ); + len = ast_uart_sdma_read(sdma, UART_RX_W_POINT(sdma_ch->ch_no)); + } + + trace_printk(": ch[%d] : %s ,len : %d\n", sdma_ch->ch_no, + sdma_ch->direction ? "tx" : "rx", len); + + if (sdma_ch->callback_fn != NULL) + (sdma_ch->callback_fn)(sdma_ch->priv, len); +} + +static irqreturn_t ast_uart_sdma_isr(int irq, void *dev_id) +{ + struct ast_sdma *sdma = (struct ast_sdma *)dev_id; + int sdma_int_num = 0; + u32 tx_sts = ast_uart_sdma_read(sdma, UART_TX_SDMA_ISR); + u32 rx_sts = ast_uart_sdma_read(sdma, UART_RX_SDMA_ISR); + + trace_printk("tx sts : %x, rx sts : %x\n", tx_sts, rx_sts); + if ((tx_sts == 0) && (rx_sts == 0)) { + pr_err("SDMA IRQ ERROR !!!\n"); + return IRQ_HANDLED; + } + + while ((sdma_int_num = ffs(rx_sts))) { + ast_uart_sdma_write(sdma, + BIT(sdma_int_num-1), UART_RX_SDMA_ISR); + ast_sdma_bufffdone( + &(sdma->dma_ch->rx_dma_info[sdma_int_num-1])); + rx_sts = rx_sts & (~BIT(sdma_int_num-1)); + } + while ((sdma_int_num = ffs(tx_sts))) { + ast_uart_sdma_write(sdma, + BIT(sdma_int_num-1), UART_TX_SDMA_ISR); + ast_sdma_bufffdone( + &(sdma->dma_ch->tx_dma_info[sdma_int_num-1])); + tx_sts = tx_sts & (~BIT(sdma_int_num-1)); + } + return IRQ_HANDLED; +} + +static int ast_uart_sdma_probe(void) +{ + int i; + struct device_node *node; + int ret; + struct ast_sdma *sdma = &ast_uart_sdma; + char *rx_dma_virt_addr; + dma_addr_t rx_dma_phy_addr; + + sdma->dma_ch = kzalloc(sizeof(struct ast_sdma_ch), GFP_KERNEL); + if (!sdma->dma_ch) + return -ENOMEM; + + // sdma memory mapping + node = of_find_compatible_node(NULL, NULL, "aspeed,ast-uart-sdma"); + if (!node) + return -ENODEV; + + sdma->reg_base = of_iomap(node, 0); + if (IS_ERR(sdma->reg_base)) + return PTR_ERR(sdma->map); + rx_dma_virt_addr = dma_alloc_coherent(NULL, + SDMA_RX_BUFF_SIZE * AST_UART_SDMA_CH, + &rx_dma_phy_addr, GFP_KERNEL); + + if (!rx_dma_virt_addr) { + pr_err("rx_dma_virt_addr Err:dma alloc Failed\n"); + return -ENOMEM; + } + for (i = 0; i < AST_UART_SDMA_CH; i++) { + // TX ------------------------ + sdma->dma_ch->tx_dma_info[i].enable = 0; + sdma->dma_ch->tx_dma_info[i].ch_no = i; + sdma->dma_ch->tx_dma_info[i].direction = 1; + ast_uart_sdma_write(sdma, 0, UART_TX_W_POINT(i)); + // RX ------------------------ + sdma->dma_ch->rx_dma_info[i].enable = 0; + sdma->dma_ch->rx_dma_info[i].ch_no = i; + sdma->dma_ch->rx_dma_info[i].direction = 0; + sdma->dma_ch->rx_dma_info[i].sdma_virt_addr = + rx_dma_virt_addr + (SDMA_RX_BUFF_SIZE * i); + sdma->dma_ch->rx_dma_info[i].dma_phy_addr = + rx_dma_phy_addr + (SDMA_RX_BUFF_SIZE * i); + ast_uart_sdma_write(sdma, + sdma->dma_ch->rx_dma_info[i].dma_phy_addr, + UART_RX_SDMA_ADDR(i)); + ast_uart_sdma_write(sdma, 0, UART_RX_R_POINT(i)); + } + + ast_uart_sdma_write(sdma, 0xffffffff, UART_TX_SDMA_REST); + ast_uart_sdma_write(sdma, 0x0, UART_TX_SDMA_REST); + + ast_uart_sdma_write(sdma, 0xffffffff, UART_RX_SDMA_REST); + ast_uart_sdma_write(sdma, 0x0, UART_RX_SDMA_REST); + + ast_uart_sdma_write(sdma, 0, UART_TX_SDMA_EN); + ast_uart_sdma_write(sdma, 0, UART_RX_SDMA_EN); + +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT + ast_uart_sdma_write(sdma, 0x200, UART_SDMA_TIMER); +#else + ast_uart_sdma_write(sdma, 0xffff, UART_SDMA_TIMER); +#endif + + // TX + ast_uart_sdma_write(sdma, 0xfff, UART_TX_SDMA_ISR); + ast_uart_sdma_write(sdma, 0, UART_TX_SDMA_IER); + + // RX + ast_uart_sdma_write(sdma, 0xfff, UART_RX_SDMA_ISR); + ast_uart_sdma_write(sdma, 0, UART_RX_SDMA_IER); + + sdma->dma_irq = of_irq_get(node, 0); + ret = request_irq(sdma->dma_irq, ast_uart_sdma_isr, 0, + "sdma-intr", sdma); + if (ret) { + pr_err("Unable to get UART SDMA IRQ %x\n", ret); + return -ENODEV; + } + + ast_uart_sdma_write(sdma, SDMA_SET_TX_BUFF_SIZE(SDMA_BUFF_SIZE_4KB) | + SDMA_SET_RX_BUFF_SIZE(SDMA_BUFF_SIZE_64KB), + UART_SDMA_CONF); + return 0; +} +// END of SDMA Layer + + +// UART Driver Layer +static unsigned int ast_serial_in(struct ast_uart_port *up, int offset) +{ + offset = map_8250_reg_offset(up, offset); + return readb(up->port.membase + offset); +} + +static void ast_serial_out(struct ast_uart_port *up, int offset, int value) +{ + /* Save the offset before it's remapped */ + offset = map_8250_reg_offset(up, offset); + writeb(value, up->port.membase + offset); +} + +#define serial_inp(up, offset) ast_serial_in(up, offset) +#define serial_outp(up, offset, value) ast_serial_out(up, offset, value) + +/* Uart divisor latch read */ +static inline int _serial_dl_read(struct ast_uart_port *up) +{ + return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8; +} + +/* Uart divisor latch write */ +static inline void _serial_dl_write(struct ast_uart_port *up, int value) +{ + serial_outp(up, UART_DLL, value & 0xff); + serial_outp(up, UART_DLM, value >> 8 & 0xff); +} + +#define serial_dl_read(up) _serial_dl_read(up) +#define serial_dl_write(up, value) _serial_dl_write(up, value) + +static void ast_uart_tx_sdma_tasklet_func(unsigned long data) +{ + struct ast_uart_port *up = to_ast_dma_uart_port( + (struct uart_port *)data); + struct circ_buf *xmit = &up->port.state->xmit; + u32 tx_pt; + + spin_lock(&up->port.lock); + + up->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); + dma_sync_single_for_device(up->port.dev, up->dma_tx_addr, + UART_XMIT_SIZE, DMA_TO_DEVICE); + tx_pt = ast_uart_get_tx_sdma_pt(up->dma_channel); + + if (tx_pt > xmit->head) { + if ((tx_pt & 0xfffc) == 0) + ast_uart_tx_sdma_update(up->dma_channel, 0xffff); + else + ast_uart_tx_sdma_update(up->dma_channel, 0); + } else { + ast_uart_tx_sdma_update(up->dma_channel, xmit->head); + } + ast_uart_tx_sdma_update(up->dma_channel, xmit->head); + spin_unlock(&up->port.lock); +} + +static void ast_uart_tx_buffdone(void *dev_id, u16 len) +{ + struct ast_uart_port *up = (struct ast_uart_port *)dev_id; + struct circ_buf *xmit = &up->port.state->xmit; + + trace_printk("line[%d] : tx len = % d\n", up->port.line, len); + spin_lock(&up->port.lock); + xmit->tail = len; + trace_printk(" line[%d], xmit->head = %d, xmit->tail = % d\n", + up->port.line, xmit->head, xmit->tail); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + if (xmit->head != xmit->tail) + tasklet_schedule(&up->tx_tasklet); + + spin_unlock(&up->port.lock); +} + +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT +static void ast_uart_rx_sdma_tasklet_func(unsigned long data) +{ + struct ast_uart_port *up = to_ast_dma_uart_port( + (struct uart_port *)data); + struct tty_port *port = &up->port.state->port; + struct circ_buf *rx_ring = &up->rx_dma_buf; + + int count; + int copy = 0; + + trace_printk("line[%d], rx_ring->head = % d, rx_ring->tail = % d\n", + up->port.line, rx_ring->head, rx_ring->tail); + + spin_lock(&up->port.lock); + if (rx_ring->head > rx_ring->tail) { + count = rx_ring->head - rx_ring->tail; + copy = tty_insert_flip_string(port, + rx_ring->buf + rx_ring->tail, count); + } else if (rx_ring->head < rx_ring->tail) { + count = SDMA_RX_BUFF_SIZE - rx_ring->tail; + copy = tty_insert_flip_string(port, + rx_ring->buf + rx_ring->tail, count); + } else { + count = 0; + } + + if (copy != count) + dev_err(&GET_DEV(up), "RxData copy to tty layer failed\n"); + if (count) { + rx_ring->tail += count; + rx_ring->tail &= (SDMA_RX_BUFF_SIZE - 1); + up->port.icount.rx += count; + tty_flip_buffer_push(port); + ast_uart_rx_sdma_update(up->dma_channel, rx_ring->tail); + } + spin_unlock(&up->port.lock); +} + +static void ast_uart_rx_buffdone(void *dev_id, u16 len) +{ + struct ast_uart_port *up = (struct ast_uart_port *)dev_id; + struct circ_buf *rx_ring = &up->rx_dma_buf; + + trace_printk("line[%d], head = %d,len:%d\n", + up->port.line, up->rx_dma_buf.head, len); + + spin_lock(&up->port.lock); + rx_ring->head = len; + spin_unlock(&up->port.lock); + tasklet_schedule(&up->rx_tasklet); +} + +#else +static void ast_uart_rx_timer_func(struct timer_list *t) +{ + struct ast_uart_port *up = from_timer(up, t, rx_timer); + struct tty_port *port = &up->port.state->port; + struct circ_buf *rx_ring = &up->rx_dma_buf; + int count, copy = 0; + + trace_printk("line[%d], rx_ring->head = % d, rx_ring->tail = % d\n", + up->port.line, rx_ring->head, rx_ring->tail); + + rx_ring->head = ast_uart_get_rx_sdma_pt(up->dma_channel); + + del_timer(&up->rx_timer); + + if (rx_ring->head > rx_ring->tail) { + ast_uart_set_sdma_time_out(0xffff); + count = rx_ring->head - rx_ring->tail; + copy = tty_insert_flip_string(port, + rx_ring->buf + rx_ring->tail, count); + } else if (rx_ring->head < rx_ring->tail) { + ast_uart_set_sdma_time_out(0xffff); + count = SDMA_RX_BUFF_SIZE - rx_ring->tail; + copy = tty_insert_flip_string(port, + rx_ring->buf + rx_ring->tail, count); + } else { + count = 0; + trace_printk("@@--%s-- ch = 0x%x\n", __func__, ch); + } + + if (copy != count) + dev_err(&GET_DEV(up), "RxData copy to tty layer failed\n"); + + if (count) { + rx_ring->tail += count; + rx_ring->tail &= (SDMA_RX_BUFF_SIZE - 1); + } + if (count) { + trace_printk("\n count = % d\n", count); + up->port.icount.rx += count; + spin_lock(&up->port.lock); + tty_flip_buffer_push(port); + spin_unlock(&up->port.lock); + trace_printk("update rx_ring->tail % x\n", rx_ring->tail); + ast_uart_rx_sdma_update(up->dma_channel, rx_ring->tail); + up->workaround = 1; + } else { + if (up->workaround) { + up->workaround++; + if (up->workaround > 1) + ast_uart_set_sdma_time_out(0); + else + ast_uart_set_sdma_time_out(0xffff); + } + } + add_timer(&up->rx_timer); +} +#endif + +/* + * FIFO support. + */ +inline void ast25xx_uart_clear_fifos(struct ast_uart_port *p) +{ + serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_outp(p, UART_FCR, + UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_outp(p, UART_FCR, 0); +} + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. + */ +static void autoconfig(struct ast_uart_port *up) +{ + unsigned long flags; + + trace_printk("line[%d]\n", up->port.line); + if (!up->port.iobase && !up->port.mapbase && !up->port.membase) + return; + + trace_printk("ttyDMA%d : autoconf (0x%04lx, 0x%p) : ", up->port.line, + up->port.iobase, up->port.membase); + + spin_lock_irqsave(&up->port.lock, flags); + + up->capabilities = 0; + up->bugs = 0; + + up->port.type = PORT_16550A; + up->capabilities |= UART_CAP_FIFO; + + up->port.fifosize = uart_config[up->port.type].fifo_size; + up->capabilities = uart_config[up->port.type].flags; + up->tx_loadsz = uart_config[up->port.type].tx_loadsz; + + if (up->port.type == PORT_UNKNOWN) + goto out; + + /* + * Reset the UART. + */ + ast25xx_uart_clear_fifos(up); + ast_serial_in(up, UART_RX); + serial_outp(up, UART_IER, 0); + +out: + spin_unlock_irqrestore(&up->port.lock, flags); + trace_printk("type=%s\n", uart_config[up->port.type].name); +} + +static inline void __stop_tx(struct ast_uart_port *p) +{ + if (p->ier & UART_IER_THRI) { + p->ier &= ~UART_IER_THRI; + ast_serial_out(p, UART_IER, p->ier); + } +} + +void ast25xx_uart_stop_tx(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + + trace_printk("line[%d]\n", up->port.line); + __stop_tx(up); +} + +static void transmit_chars(struct ast_uart_port *up); + +static void ast25xx_uart_start_tx(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + + trace_printk("line[%d]\n", port->line); + tasklet_schedule(&up->tx_tasklet); +} + +static void ast25xx_uart_stop_rx(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + + trace_printk("line[%d]\n", port->line); + up->ier &= ~UART_IER_RLSI; + up->port.read_status_mask &= ~UART_LSR_DR; + ast_serial_out(up, UART_IER, up->ier); +} + +static void ast25xx_uart_enable_ms(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + + trace_printk("line[%d]\n", port->line); + up->ier |= UART_IER_MSI; + ast_serial_out(up, UART_IER, up->ier); +} + +static void transmit_chars(struct ast_uart_port *up) +{ + struct circ_buf *xmit = &up->port.state->xmit; + int count; + + if (up->port.x_char) { + serial_outp(up, UART_TX, up->port.x_char); + up->port.icount.tx++; + up->port.x_char = 0; + return; + } + if (uart_tx_stopped(&up->port)) { + ast25xx_uart_stop_tx(&up->port); + return; + } + if (uart_circ_empty(xmit)) { + __stop_tx(up); + return; + } + + count = up->tx_loadsz; + do { + ast_serial_out(up, UART_TX, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + up->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + if (uart_circ_empty(xmit)) + __stop_tx(up); +} + +static unsigned int check_modem_status(struct ast_uart_port *up) +{ + unsigned int status = ast_serial_in(up, UART_MSR); + + trace_printk("line[%d]\n", up->port.line); + status |= up->msr_saved_flags; + up->msr_saved_flags = 0; + if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI + && up->port.state != NULL) { + if (status & UART_MSR_TERI) + up->port.icount.rng++; + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(&up->port, + status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&up->port, + status & UART_MSR_CTS); + + wake_up_interruptible(&up->port.state->port.delta_msr_wait); + } + + return status; +} + +/* + * handles the interrupt from one port. + */ +static inline void ast25xx_uart_handle_port(struct ast_uart_port *up) +{ + unsigned int status; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + + status = serial_inp(up, UART_LSR); + + trace_printk("status = %x\n", status); + + check_modem_status(up); + if (status & UART_LSR_THRE) + transmit_chars(up); + + spin_unlock_irqrestore(&up->port.lock, flags); +} + +/* + * serial driver's interrupt routine. + */ +static irqreturn_t ast_uart_interrupt(int irq, void *dev_id) +{ + struct irq_info *i = dev_id; + int pass_counter = 0, handled = 0, end = 0; + + trace_printk("(%d)-", irq); + spin_lock(&i->lock); + + do { + struct ast_uart_port *up; + unsigned int iir; + + up = (struct ast_uart_port *)(i->up); + + iir = ast_serial_in(up, UART_IIR); + if (!(iir & UART_IIR_NO_INT)) { + ast25xx_uart_handle_port(up); + handled = 1; + + } else + end = 1; + + if (pass_counter++ > PASS_LIMIT) { + pr_err("ast-uart-dma:too much work for irq%d\n", irq); + break; + } + } while (end); + + spin_unlock(&i->lock); + + trace_printk("-(%d)\n", irq); + + return IRQ_RETVAL(handled); +} + +static unsigned int ast25xx_uart_tx_empty(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned long flags; + unsigned int lsr; + + trace_printk("line[%d]\n", up->port.line); + + spin_lock_irqsave(&up->port.lock, flags); + lsr = ast_serial_in(up, UART_LSR); + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + spin_unlock_irqrestore(&up->port.lock, flags); + + return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0; +} + +static unsigned int ast25xx_uart_get_mctrl(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned int status; + unsigned int ret; + + status = check_modem_status(up); + + ret = 0; + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} + +static void ast25xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned char mcr = 0; + + mctrl = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; + + ast_serial_out(up, UART_MCR, mcr); +} + +static void ast25xx_uart_break_ctl(struct uart_port *port, int break_state) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + ast_serial_out(up, UART_LCR, up->lcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static int ast25xx_uart_startup(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + // TX DMA + struct circ_buf *xmit = &up->port.state->xmit; + unsigned long flags; + unsigned char lsr, iir; + int retval; + int irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0; + + trace_printk("line[%d]\n", port->line); + up->capabilities = uart_config[up->port.type].flags; + up->mcr = 0; + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + ast25xx_uart_clear_fifos(up); + + /* + * Clear the interrupt registers. + */ + (void)serial_inp(up, UART_LSR); + (void)serial_inp(up, UART_RX); + (void)serial_inp(up, UART_IIR); + (void)serial_inp(up, UART_MSR); + + ast_uart_irq[0].up = up; + retval = request_irq(up->port.irq, ast_uart_interrupt, irq_flags, + "ast-uart-dma", ast_uart_irq); + if (retval) + return retval; + + /* + * Now, initialize the UART + */ + serial_outp(up, UART_LCR, UART_LCR_WLEN8); + + spin_lock_irqsave(&up->port.lock, flags); + up->port.mctrl |= TIOCM_OUT2; + + ast25xx_uart_set_mctrl(&up->port, up->port.mctrl); + + /* + * Do a quick test to see if we receive an + * interrupt when we enable the TX irq. + */ + serial_outp(up, UART_IER, UART_IER_THRI); + lsr = ast_serial_in(up, UART_LSR); + iir = ast_serial_in(up, UART_IIR); + serial_outp(up, UART_IER, 0); + + if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + if (!(up->bugs & UART_BUG_TXEN)) { + up->bugs |= UART_BUG_TXEN; + pr_debug("ttyDMA%d-enabling bad tx status\n", + port->line); + } + } else { + up->bugs &= ~UART_BUG_TXEN; + } + + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Clear the interrupt registers again for luck, and clear the + * saved flags to avoid getting false values from polling + * routines or the previous session. + */ + serial_inp(up, UART_LSR); + serial_inp(up, UART_RX); + serial_inp(up, UART_IIR); + serial_inp(up, UART_MSR); + up->lsr_saved_flags = 0; + up->msr_saved_flags = 0; + + // RX DMA + up->rx_dma_buf.head = 0; + up->rx_dma_buf.tail = 0; + up->port.icount.rx = 0; + + up->tx_done = 1; + up->tx_count = 0; + + up->rx_dma_buf.head = 0; + up->rx_dma_buf.tail = 0; +#ifndef CONFIG_AST_UART_DMA_RX_INTERRUPT + up->workaround = 0; +#endif + ast_uart_rx_sdma_ctrl(up->dma_channel, AST_UART_DMAOP_STOP); + ast_uart_rx_sdma_ctrl(up->dma_channel, AST_UART_DMAOP_TRIGGER); +#ifndef CONFIG_AST_UART_DMA_RX_INTERRUPT + add_timer(&up->rx_timer); +#endif + up->tx_dma_buf.head = 0; + up->tx_dma_buf.tail = 0; + up->tx_dma_buf.buf = xmit->buf; + + trace_printk("head:0x%x tail:0x%x\n", xmit->head, xmit->tail); + xmit->head = 0; + xmit->tail = 0; + + up->dma_tx_addr = dma_map_single(port->dev, up->tx_dma_buf.buf, + UART_XMIT_SIZE, DMA_TO_DEVICE); + + ast_uart_tx_sdma_ctrl(up->dma_channel, AST_UART_DMAOP_STOP); + ast_uart_tx_sdma_enqueue(up->dma_channel, up->dma_tx_addr); + ast_uart_tx_sdma_update(up->dma_channel, 0); + ast_uart_tx_sdma_ctrl(up->dma_channel, AST_UART_DMAOP_TRIGGER); + + return 0; +} + +static void ast25xx_uart_shutdown(struct uart_port *port) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned long flags; + + trace_printk("line[%d]\n", port->line); + + up->ier = 0; + serial_outp(up, UART_IER, 0); + + spin_lock_irqsave(&up->port.lock, flags); + up->port.mctrl &= ~TIOCM_OUT2; + + ast25xx_uart_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Disable break condition and FIFOs + */ + ast_serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); + ast25xx_uart_clear_fifos(up); + + (void)ast_serial_in(up, UART_RX); + + ast_uart_rx_sdma_ctrl(up->dma_channel, AST_UART_DMAOP_PAUSE); +#ifndef CONFIG_AST_UART_DMA_RX_INTERRUPT + del_timer_sync(&up->rx_timer); +#endif + free_irq(up->port.irq, ast_uart_irq); +} + +static unsigned int ast25xx_uart_get_divisor(struct uart_port *port, + unsigned int baud) +{ + unsigned int quot; + + quot = uart_get_divisor(port, baud); + return quot; +} + +static void ast25xx_uart_set_termios(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + struct ast_uart_port *up = to_ast_dma_uart_port(port); + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; + + switch (termios->c_cflag & CSIZE) { + case CS5: + cval = UART_LCR_WLEN5; + break; + case CS6: + cval = UART_LCR_WLEN6; + break; + case CS7: + cval = UART_LCR_WLEN7; + break; + default: + case CS8: + cval = UART_LCR_WLEN8; + break; + } + + if (termios->c_cflag & CSTOPB) + cval |= UART_LCR_STOP; + if (termios->c_cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(termios->c_cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (termios->c_cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); + quot = ast25xx_uart_get_divisor(port, baud); + + if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { + if (baud < 2400) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; + else + fcr = uart_config[up->port.type].fcr; + } + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (termios->c_iflag & INPCK) + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (termios->c_iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= UART_LSR_BI; + + /* + * Characters to ignore + */ + up->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (termios->c_iflag & IGNBRK) { + up->port.ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_OE; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((termios->c_cflag & CREAD) == 0) + up->port.ignore_status_mask |= UART_LSR_DR; + + /* + * CTS flow control flag and modem status interrupts + */ + up->ier &= ~UART_IER_MSI; + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->ier |= UART_IER_MSI; + + ast_serial_out(up, UART_IER, up->ier); + + serial_outp(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + + serial_dl_write(up, quot); + + /* + * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR + * is written without DLAB set, this mode will be disabled. + */ + + serial_outp(up, UART_LCR, cval); /* reset DLAB */ + up->lcr = cval; /* Save LCR */ + if (fcr & UART_FCR_ENABLE_FIFO) { + /* emulated UARTs (Lucent Venus 167x) need two steps */ + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + } + serial_outp(up, UART_FCR, fcr); /* set fcr */ + ast25xx_uart_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); +} + +static void ast25xx_uart_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct ast_uart_port *p = (struct ast_uart_port *)port; + + if (p->pm) + p->pm(port, state, oldstate); +} + +/* + * Resource handling. + */ +static int ast25xx_uart_request_std_resource(struct ast_uart_port *up) +{ + unsigned int size = 8 << up->port.regshift; + int ret = 0; + + if (!up->port.mapbase) + return ret; + + if (!request_mem_region(up->port.mapbase, size, "ast-uart-dma")) { + ret = -EBUSY; + return ret; + } + + if (up->port.flags & UPF_IOREMAP) { + up->port.membase = ioremap_nocache(up->port.mapbase, size); + if (!up->port.membase) { + release_mem_region(up->port.mapbase, size); + ret = -ENOMEM; + return ret; + } + } + return ret; +} + +static void ast25xx_uart_release_std_resource(struct ast_uart_port *up) +{ + unsigned int size = 8 << up->port.regshift; + + if (!up->port.mapbase) + return; + + if (up->port.flags & UPF_IOREMAP) { + iounmap(up->port.membase); + up->port.membase = NULL; + } + release_mem_region(up->port.mapbase, size); +} + +static void ast25xx_uart_release_port(struct uart_port *port) +{ + struct ast_uart_port *up = (struct ast_uart_port *)port; + + ast25xx_uart_release_std_resource(up); +} + +static int ast25xx_uart_request_port(struct uart_port *port) +{ + struct ast_uart_port *up = (struct ast_uart_port *)port; + int ret; + + ret = ast25xx_uart_request_std_resource(up); + if (ret == 0) + ast25xx_uart_release_std_resource(up); + + return ret; +} + +static void ast25xx_uart_config_port(struct uart_port *port, int flags) +{ + struct ast_uart_port *up = (struct ast_uart_port *)port; + int ret; + + /* + * Find the region that we can probe for. This in turn + * tells us whether we can probe for the type of port. + */ + ret = ast25xx_uart_request_std_resource(up); + if (ret < 0) + return; + + if (flags & UART_CONFIG_TYPE) + autoconfig(up); + + if (up->port.type == PORT_UNKNOWN) + ast25xx_uart_release_std_resource(up); +} + +static int ast25xx_uart_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + return 0; +} + +static const char *ast25xx_uart_type(struct uart_port *port) +{ + int type = port->type; + + if (type >= ARRAY_SIZE(uart_config)) + type = 0; + return uart_config[type].name; +} + +static const struct uart_ops ast25xx_uart_pops = { + .tx_empty = ast25xx_uart_tx_empty, + .set_mctrl = ast25xx_uart_set_mctrl, + .get_mctrl = ast25xx_uart_get_mctrl, + .stop_tx = ast25xx_uart_stop_tx, + .start_tx = ast25xx_uart_start_tx, + .stop_rx = ast25xx_uart_stop_rx, + .enable_ms = ast25xx_uart_enable_ms, + .break_ctl = ast25xx_uart_break_ctl, + .startup = ast25xx_uart_startup, + .shutdown = ast25xx_uart_shutdown, + .set_termios = ast25xx_uart_set_termios, + .pm = ast25xx_uart_pm, + .type = ast25xx_uart_type, + .release_port = ast25xx_uart_release_port, + .request_port = ast25xx_uart_request_port, + .config_port = ast25xx_uart_config_port, + .verify_port = ast25xx_uart_verify_port, +}; + +static void __init ast25xx_uart_isa_init_ports(void) +{ + static int first = 1; + int i; + + if (!first) + return; + first = 0; + + for (i = 0; i < nr_uarts; i++) { + struct ast_uart_port *up = &ast_uart_ports[i]; + + up->port.line = i; + spin_lock_init(&up->port.lock); + + /* + * ALPHA_KLUDGE_MCR needs to be killed. + */ + up->mcr_mask = ~ALPHA_KLUDGE_MCR; + up->mcr_force = ALPHA_KLUDGE_MCR; + up->port.ops = &ast25xx_uart_pops; + } +} + +static void __init ast25xx_uart_register_ports(struct uart_driver *drv, + struct device *dev) +{ + int i; + + ast25xx_uart_isa_init_ports(); + + for (i = 0; i < nr_uarts; i++) { + struct ast_uart_port *up = &ast_uart_ports[i]; + + up->port.dev = dev; + uart_add_one_port(drv, &up->port); + } +} + + +static struct ast_uart_port * +ast25xx_uart_find_match_or_unused(struct uart_port *port) +{ + int i; + + /* + * First, find a port entry which matches. + */ + for (i = 0; i < nr_uarts; i++) + if (uart_match_port(&ast_uart_ports[i].port, port)) + return &ast_uart_ports[i]; + + /* + * We didn't find a matching entry, so look for the first + * free entry. We look for one which hasn't been previously + * used (indicated by zero iobase). + */ + for (i = 0; i < nr_uarts; i++) + if (ast_uart_ports[i].port.type == PORT_UNKNOWN && + ast_uart_ports[i].port.iobase == 0) + return &ast_uart_ports[i]; + + /* + * That also failed. Last resort is to find any entry which + * doesn't have a real port associated with it. + */ + for (i = 0; i < nr_uarts; i++) + if (ast_uart_ports[i].port.type == PORT_UNKNOWN) + return &ast_uart_ports[i]; + + return NULL; +} + +/* + * This "device" covers _all_ ISA 8250-compatible serial devices listed + * in the table in include/asm/serial.h + */ +static struct platform_device *ast25xx_uart_platform_obj_dev; + +static struct uart_driver ast25xx_uart_reg = { + .owner = THIS_MODULE, + .driver_name = "ast-uart-dma", + .dev_name = "ttyDMA", + .major = TTY_AST_MAJOR, + .minor = TTY_AST_MINOR, + .nr = UART_DMA_NR, + .cons = SERIAL8250_CONSOLE, +}; + + +/* + *Configure the serial port specified by the request. If the + *port exists and is in use, it is hung up and unregistered + *first. + * + *The port is then probed and if necessary the IRQ is autodetected + *If this fails an error is returned. + * + *On success the port is ready to use and the line number is returned. + */ +int ast_uart_register_port(struct uart_port *port) +{ + struct ast_uart_port *up; + int ret = -ENOSPC; + + if (port->uartclk == 0) + return -EINVAL; + + mutex_lock(&ast_uart_mutex); + + up = ast25xx_uart_find_match_or_unused(port); + if (up) { + uart_remove_one_port(&ast25xx_uart_reg, &up->port); + up->port.iobase = port->iobase; + up->port.membase = port->membase; + up->port.irq = port->irq; + up->port.uartclk = port->uartclk; + up->port.fifosize = port->fifosize; + up->port.regshift = port->regshift; + up->port.iotype = port->iotype; + up->port.flags = port->flags | UPF_BOOT_AUTOCONF; + up->port.mapbase = port->mapbase; + up->port.private_data = port->private_data; + if (port->dev) + up->port.dev = port->dev; + + ret = uart_add_one_port(&ast25xx_uart_reg, &up->port); + if (ret == 0) + ret = up->port.line; + + spin_lock_init(&up->lock); + + tasklet_init(&up->tx_tasklet, ast_uart_tx_sdma_tasklet_func, + (unsigned long)up); +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT + tasklet_init(&up->rx_tasklet, ast_uart_rx_sdma_tasklet_func, + (unsigned long)up); +#else + up->rx_timer.expires = jiffies + (HZ); + up->rx_timer.function = ast_uart_rx_timer_func; + timer_setup(&up->rx_timer, ast_uart_rx_timer_func, 0); +#endif + } + + mutex_unlock(&ast_uart_mutex); + return ret; +} + +void ast_uart_unregister_port(int line) +{ + struct ast_uart_port *up = &ast_uart_ports[line]; + + mutex_lock(&ast_uart_mutex); + uart_remove_one_port(&ast25xx_uart_reg, &up->port); + if (ast25xx_uart_platform_obj_dev) { + up->port.flags &= ~UPF_BOOT_AUTOCONF; + up->port.type = PORT_UNKNOWN; + up->port.dev = &ast25xx_uart_platform_obj_dev->dev; + uart_add_one_port(&ast25xx_uart_reg, &up->port); + } else { + up->port.dev = NULL; + } + mutex_unlock(&ast_uart_mutex); +} + +/* + * Register a set of serial devices attached to a platform device. The + * list is terminated with a zero flags entry, which means we expect + * all entries to have at least UPF_BOOT_AUTOCONF set. + */ +static int port_index; +struct clk *clk; + +static int ast25xx_uart_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct uart_port port; + struct ast_uart_port *up = NULL; + + int ret = 0; + u32 read, dma_channel = 0; + struct resource *res; + + if (UART_XMIT_SIZE > DMA_BUFF_SIZE) + trace_printk("UART_XMIT_SIZE > DMA_BUFF_SIZE : Please Check\n"); + + up = &ast_uart_ports[port_index]; + memset(&port, 0, sizeof(struct uart_port)); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res == NULL) { + dev_err(&pdev->dev, "IRQ resource not found"); + return -ENODEV; + } + port.irq = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Register base not found"); + return -ENODEV; + } + port.mapbase = res->start; + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "missing controller clock"); + return PTR_ERR(clk); + } + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(&pdev->dev, "failed enabling DMA UART Clk: %d\n", ret); + return ret; + } + port.uartclk = clk_get_rate(clk); + + ret = of_property_read_u32(np, "reg-shift", &read); + if (ret) { + dev_err(&pdev->dev, "Failed to read reg-shift from DT"); + return -ret; + } + port.regshift = read; + ret = of_property_read_u32(np, "dma-channel", &read); + if (ret) { + dev_err(&pdev->dev, "Failed to read dma-channel from DT"); + return -ret; + } + dma_channel = read; + up->dma_channel = dma_channel; + port.iotype = UPIO_MEM; + port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.dev = &pdev->dev; + //port.private_data = up->dma_channel; + if (share_irqs) + port.flags |= UPF_SHARE_IRQ; + + ret = ast_uart_register_port(&port); + if (ret < 0) { + dev_err(&pdev->dev, + "unable to registr port at index%d (IO%lx MEM%llx IRQ%d):%d\n", + port_index, port.iobase, (unsigned long long)port.mapbase, + port.irq, ret); + return ret; + } + +#ifdef CONFIG_AST_UART_DMA_RX_INTERRUPT + up->rx_dma_buf.buf = + ast_uart_rx_sdma_request(up->dma_channel, ast_uart_rx_buffdone, + up); + if (up->rx_dma_buf.buf < 0) { + trace_printk("Error : failed to get rx dma channel[%d]\n", + up->dma_channel); + goto out_ast_uart_unregister_port; + } + +#else + up->rx_dma_buf.buf = ast_uart_rx_sdma_request( + up->dma_channel, up); + if (up->rx_dma_buf.buf < 0) { + trace_printk("Error : failed to get rx dma channel[%d]\n", + up->dma_channel); + goto out_ast_uart_unregister_port; + } +#endif + ret = ast_uart_tx_sdma_request(up->dma_channel, + ast_uart_tx_buffdone, up); + if (ret < 0) { + pr_debug("Error : failed to get tx dma channel[%d]\n", + up->dma_channel); + goto out_ast_uart_unregister_port; + } + + up->ast_uart_pdev = pdev; + port_index++; + return 0; + +out_ast_uart_unregister_port: + up = &ast_uart_ports[port_index]; + + if (up->port.dev == &pdev->dev) + ast_uart_unregister_port(up->port.line); + return ret; +} + +/* + * Remove serial ports registered against a platform device. + */ +static int ast25xx_uart_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < nr_uarts; i++) { + struct ast_uart_port *up = &ast_uart_ports[i]; + + if (up->port.dev == &pdev->dev) + ast_uart_unregister_port(i); + } + return 0; +} + +static int ast25xx_uart_suspend(struct platform_device *pdev, + pm_message_t state) +{ + int i; + + for (i = 0; i < UART_DMA_NR; i++) { + struct ast_uart_port *up = &ast_uart_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &pdev->dev) + uart_suspend_port(&ast25xx_uart_reg, &up->port); + } + + return 0; +} + +static int ast25xx_uart_resume(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < UART_DMA_NR; i++) { + struct ast_uart_port *up = &ast_uart_ports[i]; + + if (up->port.type != PORT_UNKNOWN && up->port.dev == &pdev->dev) + serial8250_resume_port(i); + } + + return 0; +} +static const struct of_device_id ast_serial_dt_ids[] = { + { .compatible = "aspeed,ast-sdma-uart", }, + { /* sentinel */ } +}; + +static struct platform_driver ast25xx_uart_ast_dma_driver = { + .probe = ast25xx_uart_probe, + .remove = ast25xx_uart_remove, + .suspend = ast25xx_uart_suspend, + .resume = ast25xx_uart_resume, + .driver = { + .name = "ast2500-uart-dma-drv", + .of_match_table = of_match_ptr(ast_serial_dt_ids), + }, +}; + +static int __init ast_uart_init(void) +{ + int ret; + + if (nr_uarts > UART_DMA_NR) + nr_uarts = UART_DMA_NR; + ret = ast_uart_sdma_probe(); + if (ret) { + pr_err("ast_uart_sdma_probe Failed ret = %d\n", ret); + goto out; + } + pr_debug("UART driver with DMA%d ports IRQ sharing %sabled\n", + nr_uarts, share_irqs ? "en" : "dis"); + + spin_lock_init(&ast_uart_irq[0].lock); + + ret = uart_register_driver(&ast25xx_uart_reg); + if (ret) + goto out; + + ast25xx_uart_platform_obj_dev = + platform_device_alloc("ast-uart-dma", PLAT8250_DEV_LEGACY); + if (!ast25xx_uart_platform_obj_dev) { + ret = -ENOMEM; + goto unreg_uart_drv; + } + + ret = platform_device_add(ast25xx_uart_platform_obj_dev); + if (ret) + goto put_dev; + + ast25xx_uart_register_ports(&ast25xx_uart_reg, + &ast25xx_uart_platform_obj_dev->dev); + + ret = platform_driver_register(&ast25xx_uart_ast_dma_driver); + if (ret == 0) + goto out; + + platform_device_del(ast25xx_uart_platform_obj_dev); +put_dev: + platform_device_put(ast25xx_uart_platform_obj_dev); +unreg_uart_drv: + uart_unregister_driver(&ast25xx_uart_reg); +out: + return ret; +} + +static void __exit ast_uart_exit(void) +{ + struct platform_device *isa_dev = ast25xx_uart_platform_obj_dev; + + ast25xx_uart_platform_obj_dev = NULL; + platform_driver_unregister(&ast25xx_uart_ast_dma_driver); + platform_device_unregister(isa_dev); + uart_unregister_driver(&ast25xx_uart_reg); +} + +module_init(ast_uart_init); +module_exit(ast_uart_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Aspeed's AST2500 DMA UART driver"); From patchwork Fri Jul 26 13:27:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sudheer v X-Patchwork-Id: 1137456 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45w8wp55VGz9sNk for ; Fri, 26 Jul 2019 23:26:02 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ABSnbEq7"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 45w8wm0TcjzDqG9 for ; Fri, 26 Jul 2019 23:26:00 +1000 (AEST) X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::542; helo=mail-pg1-x542.google.com; envelope-from=open.sudheer@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ABSnbEq7"; dkim-atps=neutral Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 45w8wH2L5DzDqQG for ; Fri, 26 Jul 2019 23:25:35 +1000 (AEST) Received: by mail-pg1-x542.google.com with SMTP id l21so24795414pgm.3 for ; Fri, 26 Jul 2019 06:25:35 -0700 (PDT) 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; bh=Y/+vYtsCysqhzTsUB/MaZnRyWhMQc4pCqw65yISuFeg=; b=ABSnbEq7gwAOQcJS4x5BPjR9TjiZ/KtpISxsQmuCXZ9MoBHN4Pk/qbasRPH/bovbz7 /gabE+SpXbFSM52BcfmH6FOW+cYZpUHrFAGFVh8fizPuqOvg6gscdBzzH4zV6Ra9gFUx FS3FcUiD56vmqIGZNdiS1sn2xqSalRXnaG1bbbcMUXctzETi9DMsSuwH8Wp0C5rR5amq 8fvgvrVz8RmAJN+u3RtWSyqXPljlYlQt/kUcqWvyz48WGOiFZX/2A+4OmZzahiasGzN5 S7WQQZgSnCHcIMakYAnWg8SjXgfdHZrXYLKUvxDMyhX9MIM4rmqzX4STqIu3Tn1DX5kX yhJQ== 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; bh=Y/+vYtsCysqhzTsUB/MaZnRyWhMQc4pCqw65yISuFeg=; b=BKFQFCrFCflS6oMw1reYCNB5XtYcDq+SfhRQeXhccL7REZxAI0Z9+srfqWB+ZOJHaG KbxWMOB+AxKXrwIgUnxWYFpAGMo3HfUWlIIE0TlHBUlKxQ8Z7FvHo11p00VCl7Hdf/9g JD6d3Sp/g55ZHY5JQvP0mOEV4+fXx8dhO9IeKVwiAlWsIdgodPdkwBhKbliIXOshGe04 VR8FE2yVBWYcHAWY6IB0hfVkJe6pe47TbJPHfnr4T03M03ttQhHgoFgavJc/5EiLbBI4 GPel94wNu0lSsy1dtzpQfIq03znyV12BpfAdDdTWNtYwV5QZuLoPo07z3l41WQMH04wU VroQ== X-Gm-Message-State: APjAAAXco8ePEesqrAKLEfQ6RJVgsFWcq+BkYfJe/v6m1pY1bEpCtT9N ITIQvXxOOQoxx1EgxAcqB7c= X-Google-Smtp-Source: APXvYqyZxkac6LiJUmd4XgiaCjs6pQWpAXR97GUjfDJ6ofnoz0LFeonQ/46Uw+0sk31ucCSvExwYQw== X-Received: by 2002:a63:1d2:: with SMTP id 201mr56974280pgb.307.1564147532616; Fri, 26 Jul 2019 06:25:32 -0700 (PDT) Received: from Pilot130.192.168.0.22 (211-20-114-70.HINET-IP.hinet.net. [211.20.114.70]) by smtp.googlemail.com with ESMTPSA id k36sm54544603pgl.42.2019.07.26.06.25.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jul 2019 06:25:32 -0700 (PDT) From: "sudheer.v" To: gregkh@linuxfoundation.org, jslaby@suse.com, joel@jms.id.au, andrew@aj.id.au, benh@kernel.crashing.org, robh+dt@kernel.org, mark.rutland@arm.com, shivahshankar.shankarnarayanrao@aspeedtech.com, sudheer.veliseti@aspeedtech.com Subject: [patch v4 2/5] build configuration for AST2500 DMA UART driver Date: Fri, 26 Jul 2019 18:57:17 +0530 Message-Id: <1564147640-30753-3-git-send-email-open.sudheer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> References: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, sudheer veliseti Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" From: sudheer veliseti build config for DMA based UART driver in AST2500. Total Available UARTs in AST2500 are 4 Signed-off-by: sudheer veliseti --- Changes from v3->v4: - config name changed to SERIAL_AST_DMA_UART - new config AST_UART_DMA_RX_INTERRUPT introduced for selectin between DMA interrupt based RX vs timer based uart RX Changes in v2->v3: - change logs added drivers/tty/serial/8250/Kconfig | 43 ++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Makefile | 1 + 2 files changed, 44 insertions(+) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 15c2c5463835..7052ab0f4894 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -189,6 +189,49 @@ config SERIAL_8250_RUNTIME_UARTS with the module parameter "nr_uarts", or boot-time parameter 8250.nr_uarts +config SERIAL_AST_DMA_UART + tristate "AST UART driver with DMA" + select SERIAL_CORE + help + UART driver with DMA support for Aspeed BMC AST25XX. + this driver supports UARTs in AST2500. It uses + DMA channel of DMA engines present in these chips. + since this dma engine is used only by UARTs it is not + added as a separate DMA driver instead added as a layer + within UART driver. + +config AST_UART_DMA_RX_INTERRUPT + bool "DMA interrupt of UART RX" + depends on SERIAL_AST_DMA_UART + default y + help + This config is Enabled by default,which means Rx part + of UART is handled by DMA interrupt. + if the version of chip AST2500 doesn't support + DMA interrupt based RX,then Disable this option.Refer + driver code to see how Rx is handled by timer,if Rx + interrupt is not available. + + +config AST_NR_DMA_UARTS + int "Maximum number of uart dma serial ports" + depends on SERIAL_AST_DMA_UART + default "4" + help + Set this to the number of serial ports you want the driver + to support. This includes any ports discovered via ACPI or + PCI enumeration and any ports that may be added at run-time + via hot-plug, or any ISA multi-port serial cards. + +config AST_RUNTIME_DMA_UARTS + int "Number of uart dma serial ports to register at runtime" + depends on SERIAL_AST_DMA_UART + range 0 AST_NR_DMA_UARTS + default "4" + help + Set this to the maximum number of serial ports you want + the kernel to register at boot time. + config SERIAL_8250_EXTENDED bool "Extended 8250/16550 serial driver options" depends on SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 18751bc63a84..251f2e85efa1 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o +obj-$(CONFIG_SERIAL_AST_DMA_UART) += 8250_ast2500_uart_dma.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt From patchwork Fri Jul 26 13:27:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sudheer v X-Patchwork-Id: 1137457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45w8x52Pbrz9s8m for ; Fri, 26 Jul 2019 23:26:17 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="h0pEeb8e"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 45w8x50kQbzDqGc for ; Fri, 26 Jul 2019 23:26:17 +1000 (AEST) X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::542; helo=mail-pg1-x542.google.com; envelope-from=open.sudheer@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="h0pEeb8e"; dkim-atps=neutral Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 45w8wM19mRzDqQG for ; Fri, 26 Jul 2019 23:25:39 +1000 (AEST) Received: by mail-pg1-x542.google.com with SMTP id s1so18492196pgr.2 for ; Fri, 26 Jul 2019 06:25:39 -0700 (PDT) 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; bh=MquKBd9hqVjp/9J/EBQwb+pNJa32VY/RVtfqOZkVTYM=; b=h0pEeb8eJmv0OWlzU8c/oZZxxlqWUWnjqI7h0wMYSo1EDOqzSN8fzh9i5qaJbRTsMJ ZXXj1+P+jyzfKrIS31BiT9UYFd05eHa3hQxp3hE/0SaWhzM+gqKTXP6Ie1ctglELY9ep bMyP82ohvp7tUxGMEFgBwZWi7dY4wrsxBNqd5SaV0Q4gJqm2cAx3IO6Vu1dAveBFKivY ji2ISZUSgNCVwozsCuOc8udRSAJAWv4qxWQ4wYL/Gu0yVu93lwdNL5oPEqi8Mp40xTY9 vZnKKuLISbJ+FK7ANJ06/n838OV7DTM0c0dTEfMUk1ojzRwTkCdZ0KBf011mhIpVN7Xd ADww== 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; bh=MquKBd9hqVjp/9J/EBQwb+pNJa32VY/RVtfqOZkVTYM=; b=MoDF2Wroqh0kNMJZ9Or7U6UwQv0xXU/hwJw1EHe9tF65d7Ser1rTTB20JSVqKi0xJH G5YiQsKsLt2yC4ppqJdtkU+ack3BVEvgVuNyN1gHDwV+rtUXgXN25b/m2ZaQbShPhQjV yyJDG4w/Qcjrd9HLNDR+VWO7G6ulg/g7hC+yFNOE07jRpM9ZqkxDFshbNYnCLpdgzZxR fyy2TmrGZX4RUdwl5w52QOXwNFOv442PNiu76ToGC+Mq/kaBjZ2msK3mFQGi3VUwkSut /DcENiFXBKRCPMT8LtwCvDvbPoUPgYSB2bWeTqQ47MwxnW/cacI5Pd9XdAV3Pf9QD4xX U7Tg== X-Gm-Message-State: APjAAAVF0amw2KxPrb1GTcQ7MhktXaUPyLGEXUYzfXBKVhzbYwP7izIE yOqjb1fORcDs8oUN/Z8UOqw= X-Google-Smtp-Source: APXvYqylom4Oby1O6RsLiZ+JCG1HqcBX0N6tZc7gxaPQuePmybgdxMkBUpAzRhY5+z/zhx5R3s/MHQ== X-Received: by 2002:a63:490a:: with SMTP id w10mr89969624pga.6.1564147537087; Fri, 26 Jul 2019 06:25:37 -0700 (PDT) Received: from Pilot130.192.168.0.22 (211-20-114-70.HINET-IP.hinet.net. [211.20.114.70]) by smtp.googlemail.com with ESMTPSA id k36sm54544603pgl.42.2019.07.26.06.25.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jul 2019 06:25:36 -0700 (PDT) From: "sudheer.v" To: gregkh@linuxfoundation.org, jslaby@suse.com, joel@jms.id.au, andrew@aj.id.au, benh@kernel.crashing.org, robh+dt@kernel.org, mark.rutland@arm.com, shivahshankar.shankarnarayanrao@aspeedtech.com, sudheer.veliseti@aspeedtech.com Subject: [patch v4 3/5] DT nodes for AST2500 DMA UART driver Date: Fri, 26 Jul 2019 18:57:18 +0530 Message-Id: <1564147640-30753-4-git-send-email-open.sudheer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> References: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, sudheer veliseti Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" From: sudheer veliseti DT node for DMA controller(ast_uart_sdma) doesn't bind to any DMA controller driver. This is because Software for DMA controller is not based on DMA framework,but is dedicated and serves only UARTs in AST2500. ast_uart_sdma node is searched by compatible string in the driver software.basic use of this node is to provide register base address of DMA controller and DMA irq number(<50>). IRQ of DMA controller is of crucial importance, which does RX and TX of UART data. uart nodes dma_uart1,2...etc binds to the platform driver. irq numbers <9>,<32>,<33>,<34> in dma_uart nodes install ISRs which are of not much interest in uart data TX/RX . Signed-off-by: sudheer veliseti --- changes from v3->v4: - changes from v2->v3: - change logs added arch/arm/boot/dts/aspeed-ast2500-evb.dts | 21 +++++++ arch/arm/boot/dts/aspeed-g5.dtsi | 71 ++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts index 5dbb33c10c4f..4da09fbe94df 100644 --- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts +++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts @@ -64,6 +64,27 @@ status = "okay"; }; +&ast_uart_sdma { + status = "okay"; +}; + +&dma_uart1 { + status = "okay"; +}; + +&dma_uart2 { + status = "okay"; +}; + +&dma_uart3 { + status = "okay"; +}; + +&dma_uart4 { + status = "okay"; +}; + + &mac0 { status = "okay"; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index 674746513031..fb7b3ed463de 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -23,10 +23,10 @@ i2c11 = &i2c11; i2c12 = &i2c12; i2c13 = &i2c13; - serial0 = &uart1; - serial1 = &uart2; - serial2 = &uart3; - serial3 = &uart4; + serial0 = &dma_uart1; + serial1 = &dma_uart2; + serial2 = &dma_uart3; + serial3 = &dma_uart4; serial4 = &uart5; serial5 = &vuart; peci0 = &peci0; @@ -497,6 +497,69 @@ status = "disabled"; }; + ast_uart_sdma: uart_sdma@1e79e000 { + compatible = "aspeed,ast-uart-sdma"; + reg = <0x1e79e000 0x400>; + interrupts = <50>; + status = "disabled"; + }; + + dma_uart1: dma_uart1@1e783000{ + compatible = "aspeed,ast-sdma-uart"; + reg = <0x1e783000 0x1000>; + reg-shift = <2>; + interrupts = <9>; + clocks = <&syscon ASPEED_CLK_GATE_UART1CLK>; + dma-channel = <0>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default + &pinctrl_rxd1_default>; + status = "disabled"; + }; + + dma_uart2: dma_uart2@1e78d000{ + compatible = "aspeed,ast-sdma-uart"; + reg = <0x1e78d000 0x1000>; + reg-shift = <2>; + interrupts = <32>; + clocks = <&syscon ASPEED_CLK_GATE_UART2CLK>; + dma-channel = <1>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd2_default + &pinctrl_rxd2_default>; + status = "disabled"; + }; + + dma_uart3: dma_uart3@1e78e000{ + compatible = "aspeed,ast-sdma-uart"; + reg = <0x1e78e000 0x1000>; + reg-shift = <2>; + interrupts = <33>; + clocks = <&syscon ASPEED_CLK_GATE_UART3CLK>; + dma-channel = <2>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd3_default + &pinctrl_rxd3_default>; + status = "disabled"; + }; + + dma_uart4: dma_uart4@1e78f000{ + compatible = "aspeed,ast-sdma-uart"; + reg = <0x1e78f000 0x1000>; + reg-shift = <2>; + interrupts = <34>; + clocks = <&syscon ASPEED_CLK_GATE_UART4CLK>; + dma-channel = <3>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd4_default + &pinctrl_rxd4_default>; + status = "disabled"; + }; + i2c: bus@1e78a000 { compatible = "simple-bus"; #address-cells = <1>; From patchwork Fri Jul 26 13:27:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sudheer v X-Patchwork-Id: 1137458 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45w8xF1Ys1z9s3l for ; Fri, 26 Jul 2019 23:26:25 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EUDfHT3Y"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 45w8xD2mcvzDqQP for ; Fri, 26 Jul 2019 23:26:24 +1000 (AEST) X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::442; helo=mail-pf1-x442.google.com; envelope-from=open.sudheer@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EUDfHT3Y"; dkim-atps=neutral Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 45w8wS2TMJzDq9Q for ; Fri, 26 Jul 2019 23:25:44 +1000 (AEST) Received: by mail-pf1-x442.google.com with SMTP id c3so1397967pfa.13 for ; Fri, 26 Jul 2019 06:25:44 -0700 (PDT) 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; bh=XnwQtA++4ZLQs18Zi/kVWI3WT0kdxj4T2Lu+EaH+lNM=; b=EUDfHT3Y1h+g5qNNasOMRbGs4FROTTau5miuZF1wBpoiCwIxlfrvi6feHwz+MTe7yf zXyLaRMXduj9kqj1QWbGuzaDVllBTUprvYCfp7LUt39JcqNTTkBnpkZWkrTnCeBdPhOS 9KmCcO/qmA/CS5V5zQ+qt5llyJYjaEgCjnzsEeZNtUeefrPFIBZjZdQDFqFvjBHsrmns GM6kH6J01Gd4FfX/YwyMyD8R5EWeBgLObSCniqX5monH6I6g6I96uhRds/gg+2WpyNsm 7P8K68ue70jt8NvnT+rF58SwQX4OQ/fPbJlL095xFhDLLhzR+zV2vYVnb6pzgSHcpDvi DBVQ== 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; bh=XnwQtA++4ZLQs18Zi/kVWI3WT0kdxj4T2Lu+EaH+lNM=; b=JSq3InqAwyPxTKhT/nIocUyHu29XkAzW/SaKOth6UxANEhEfZfM5qaZuqNxMzdTDE5 WvDUz9vweAb2zZjBseitoBv0x7cJ4Y2+mEKVwygK6XrcAxTIWuv0iXrATMl8aI619V9V MWBzqtXpVf4hNUL8hajqI8FRj/imOpV53fK0b5/t+FRDLkfwflBua0nIpFAh5/pizkDC Fj2iKTXoqjaAe5zbpwpDcjIy0aN81SXvxyyhfjJuVvndGzRX/TJXTg35+ZUrfsNRXtcn QEBZoHGzCQTvCHCFZ9A24Uy7oCpNkRyVWRJAW9Fl2BsGcgsCkdg0wKoTIp3DOtFL7csa 5i8Q== X-Gm-Message-State: APjAAAWTrgFjN3hHR6gTKO2fiTd+JfqrSab8QunsCIqxb/bqYfBfrlAN IhvsTjJSRn7Ye2e3Im3bDsw= X-Google-Smtp-Source: APXvYqzTWZbkX606qEM14eI+153drc1gKBISCMCaxjG+FvU99HV0t2kzhGHkSgxYnarXYG3KfRm3dw== X-Received: by 2002:a62:1ac8:: with SMTP id a191mr22270899pfa.164.1564147541492; Fri, 26 Jul 2019 06:25:41 -0700 (PDT) Received: from Pilot130.192.168.0.22 (211-20-114-70.HINET-IP.hinet.net. [211.20.114.70]) by smtp.googlemail.com with ESMTPSA id k36sm54544603pgl.42.2019.07.26.06.25.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jul 2019 06:25:40 -0700 (PDT) From: "sudheer.v" To: gregkh@linuxfoundation.org, jslaby@suse.com, joel@jms.id.au, andrew@aj.id.au, benh@kernel.crashing.org, robh+dt@kernel.org, mark.rutland@arm.com, shivahshankar.shankarnarayanrao@aspeedtech.com, sudheer.veliseti@aspeedtech.com Subject: [patch v4 4/5] defconfig and MAINTAINERS updated for AST2500 DMA UART driver Date: Fri, 26 Jul 2019 18:57:19 +0530 Message-Id: <1564147640-30753-5-git-send-email-open.sudheer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> References: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, sudheer veliseti Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" From: sudheer veliseti defconfig changes to add DMA based UART in AST2500 Maintainers File updated. Signed-off-by: sudheer veliseti --- Changes in v4: - config name changed to CONFIG_SERIAL_AST_DMA_UART as per convention Changes in v3: - Added changes logs MAINTAINERS | 12 ++++++++++++ arch/arm/configs/aspeed_g5_defconfig | 1 + 2 files changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 997e27ab492f..d814a52ecf99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1347,6 +1347,18 @@ F: drivers/crypto/axis F: drivers/pinctrl/pinctrl-artpec* F: Documentation/devicetree/bindings/pinctrl/axis,artpec6-pinctrl.txt +ARM/ASPEED DMA UART DRIVER +M: sudheer v +R: Joel Stanley +R: Andrew Jeffery +R: Vinod Koul +L: dmaengine@vger.kernel.org +L: openbmc@lists.ozlabs.org +L: linux-aspeed@lists.ozlabs.org +S: Maintained +F: drivers/tty/serial/8250/8250_aspeed_uart_dma.c +F: Documentation/devicetree/bindings/serial/ast-sdma-uart.txt + ARM/ASPEED I2C DRIVER M: Brendan Higgins R: Benjamin Herrenschmidt diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index 1849cbc161b4..fc17cc9ddc00 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -144,6 +144,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=6 CONFIG_SERIAL_8250_RUNTIME_UARTS=6 +CONFIG_SERIAL_AST_DMA_UART=y CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_ASPEED_VUART=y CONFIG_SERIAL_8250_SHARE_IRQ=y From patchwork Fri Jul 26 13:27:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sudheer v X-Patchwork-Id: 1137459 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45w8xL41L8z9s3l for ; Fri, 26 Jul 2019 23:26:30 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="LoDzl5dV"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 45w8xL0m6szDqQY for ; Fri, 26 Jul 2019 23:26:30 +1000 (AEST) X-Original-To: linux-aspeed@lists.ozlabs.org Delivered-To: linux-aspeed@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::541; helo=mail-pg1-x541.google.com; envelope-from=open.sudheer@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="LoDzl5dV"; dkim-atps=neutral Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 45w8wX4pMzzDqGv for ; Fri, 26 Jul 2019 23:25:48 +1000 (AEST) Received: by mail-pg1-x541.google.com with SMTP id w10so24805412pgj.7 for ; Fri, 26 Jul 2019 06:25:48 -0700 (PDT) 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; bh=DCfqG2JMRKwxzIsSj479KFdZDqfmx3j+5mtM0thRZ58=; b=LoDzl5dV4EQI2pUj8qVRXOAIoTnhZqceQpnFZnYzGnjVxpbtUcLiRPGuN6wt1cfrk8 9puIruzvHJiQfOZv5PZZd+FF2dgvSd71Ci1ZZsjg7m86JizzgmNPqKMYoXdTIvJXHsOq NwrVoe5f9PBdtRH6N66l5YJxfuFP/gD2F802dhFBTC1SiuwOy1MruAO0NLhYsCq4wZOf W0p7+pUa1PZq7pPtfk6RsgItcl4726Ceg/Hk1AB1UoURdYRIUBJi5U5lW32rWnPFVBmL ZLWuVXX3k3ADP/NhY8j8zdnTzj7neDsmjmOy8n4vuaEr5QmFHjVNvBHoTOFwObaHUPMG zgDA== 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; bh=DCfqG2JMRKwxzIsSj479KFdZDqfmx3j+5mtM0thRZ58=; b=SGmIoTkoRkuvd3yq2xvrvK+dUzOxF8yfHzVSCCyd1ODcmqA7gIFgVoEht4nROzYMH0 8oMXXzrrZyiq+scAXnbsKQD56ERZnXet0n4SaP8o3tdhgau221Yn+T2BHyHa3acVTGSZ khVayvwzMZRUuPdqV82R47P1Mk8EW6vplgPqEBinBVeGFm8ZPB8QgAWQHU+xidMFEm/d qah8oAnxfig/T/BkEDXLy42tmMlSYqfGw8v7c/cNHKFj76REQ4XvzbryOw9aKT0cWDgM A8TW1GsFlbnUvhstR6TGUSVS47XPBgqAkoEtMkYd6hXJOGi66kkOm+VtQV0gUXf9Y9QO c7pw== X-Gm-Message-State: APjAAAUgLx/pgcgiLv+742nAJg1OxZR65zbWHO5a4eHo2L/1H6inEcHR VoBX5JFGWRllfg2IGqaCNi0= X-Google-Smtp-Source: APXvYqxJ0TvnmiWTXBEyq2/z1dvr4VEXVLgB/9ZQJw4kX1R9wOUtS6Lanafe6ZYS4kpvndxZEF77AQ== X-Received: by 2002:a65:5b8e:: with SMTP id i14mr90112067pgr.188.1564147546371; Fri, 26 Jul 2019 06:25:46 -0700 (PDT) Received: from Pilot130.192.168.0.22 (211-20-114-70.HINET-IP.hinet.net. [211.20.114.70]) by smtp.googlemail.com with ESMTPSA id k36sm54544603pgl.42.2019.07.26.06.25.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jul 2019 06:25:45 -0700 (PDT) From: "sudheer.v" To: gregkh@linuxfoundation.org, jslaby@suse.com, joel@jms.id.au, andrew@aj.id.au, benh@kernel.crashing.org, robh+dt@kernel.org, mark.rutland@arm.com, shivahshankar.shankarnarayanrao@aspeedtech.com, sudheer.veliseti@aspeedtech.com Subject: [patch v4 5/5] Documentation: DT bindings AST2500 DMA UART driver Date: Fri, 26 Jul 2019 18:57:20 +0530 Message-Id: <1564147640-30753-6-git-send-email-open.sudheer@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> References: <1564147640-30753-1-git-send-email-open.sudheer@gmail.com> X-BeenThere: linux-aspeed@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux ASPEED SoC development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org, sudheer veliseti Errors-To: linux-aspeed-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Linux-aspeed" From: sudheer veliseti documentation for Dt bindings for DMA based UARTs in AST2500 Signed-off-by: sudheer veliseti --- Changes in v4: - Changes in v3: - change logs added .../bindings/serial/ast2500-dma-uart.txt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/serial/ast2500-dma-uart.txt diff --git a/Documentation/devicetree/bindings/serial/ast2500-dma-uart.txt b/Documentation/devicetree/bindings/serial/ast2500-dma-uart.txt new file mode 100644 index 000000000000..6ebc60b51d4c --- /dev/null +++ b/Documentation/devicetree/bindings/serial/ast2500-dma-uart.txt @@ -0,0 +1,43 @@ +DT Bindings DMA UART for AST25XX: + +node for DMA controller: + ast_uart_sdma: uart_sdma@1e79e000 { + compatible = "aspeed,ast-uart-sdma"; + reg = <0x1e79e000 0x400>; + interrupts = <50>; + status = "disabled"; + }; +this node doesn't binds with any driver. +DMA controller is handled as a separate SW layer, +and is included in the same driver. +This DMA controller node is included in DT +just for Register and interrupt details + + + +node for DMA-UARTS : + + +Required properties: + +- compatible: "aspeed,ast-sdma-uart" +- reg: The base address of the UART register bank +- interrupts: should contain interrupt specifier. +- clocks: Clock driving the hardware; +- pinctrl-0 : list of pinconfigurations +- dma-channel: channel of DMA-controller which is used + +Example: + + dma_uart1: dma_uart1@1e783000{ + compatible = "aspeed,ast-sdma-uart"; + reg = <0x1e783000 0x1000>; + reg-shift = <2>; + interrupts = <9>; + clocks = <&syscon ASPEED_CLK_GATE_UART1CLK>; + dma-channel = <0>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_txd1_default &pinctrl_rxd1_default>; + status = "disabled"; + };