From patchwork Fri Jul 17 06:20:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sumit Garg X-Patchwork-Id: 235674 Delivered-To: patches@linaro.org Received: by 2002:a92:d244:0:0:0:0:0 with SMTP id v4csp1428602ilg; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) X-Received: by 2002:a65:4b85:: with SMTP id t5mr7363590pgq.36.1594966895797; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594966895; cv=none; d=google.com; s=arc-20160816; b=pILALJcLFmBfLYrLXeFq4VWcX0a8WCfWkS00Qg7JWhAZDnv01VV61Gf7Gf0Yywl0Rc b4DGtn3aRxLFeHhU20KMHPDDTZ3WVOdH0OiMDvvH8dWDvQT2j0GEi5+34BMa6SGivD3g +nkt7pFQrpuREM9MIw/W7qPdm2ZdluEv1iSTzxB6RfI8W7lhXgZYn8cePzOOaQmCtCip 2ayefARcFbJDx8xWY54acNQGe1iMaiizFeBj5LUstrPC+eg7lTcfoM/iCJQD+NkFLvBi MN70WYfS5nEil+GCy+N78ttckp0eNeOpYxEa4MlBXVx9YeSMbcQzh1IdYKdavXCs8vwQ qOhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=DySdNE3Or4siCJOigOPu7wC57fOagP27AEQTL9InHV+HcKNZ6ErNRrxnld3QAqhvJe rdycEreGrXJkWv4XtMeIfp01bwxaqJRCiUeDMthCYv6yLrzCDTGe5JOnev+tqwnPKfOq R0Xl9vBQpP+oZqAR8/TR8s+670if5oABHIPvAOdM+ftytj0F4AigV9Jqdcu7dks5AMkv AKpD98jVqjWIiOXhXrBc9WE8Z1L0HOVzh9FWUmEnnUBbCtZoodTE0ZDGoXNdB7yuQPDS +shxvuLq98yA2L7ZxhwYWe2LUykYQF5Obh3m8p1m8iejKhMmzvub4FUK3f4SqEw6QvTU VoQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="hp3zE/K9"; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id d4sor9636382plo.37.2020.07.16.23.21.35 for (Google Transport Security); Thu, 16 Jul 2020 23:21:35 -0700 (PDT) Received-SPF: pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="hp3zE/K9"; spf=pass (google.com: domain of sumit.garg@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=sumit.garg@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=hp3zE/K9KZCG3FwVVl6SX8IDDdmE2zyQ5P7u3iq3sr0/f7V7X2twK9cM5dVt8r6h4F 4edybJoEzWXUNTaAEsZcHM2w9HBy8wQh2QhaLrwoQqLd2LWqCYwgR/xVdqUvVycsCfHs ECpwkwDF1ZeYiCkB6XGKIm2buF6eDLTLjze97NCXdZb7a1d9xFTTboh9dVz+L806ioOv ox7gCDSjtAlI0y9EaWp9mBFPWl2IVhlYbwZ8OJzI4Yfgetcn4mZQWCeix6tdKRWeXWRI KYSbbTSyHTDDRGriEcENrvLW6gfqdRhYamZYnaPK4pLycOZNFuUKJSJGbdC2Pk3juIan H6Fg== 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=ng8mYQGVafyTeYpy3YuECHIHVKJ+K4FPaGb92k/2f4E=; b=mqLQHaPwFeTs0Ybs53ogA2u6wT9Nisz+CxFmj7hIQBWqizKDnpfIfmiRB8x8GZSSEG 0lW8Adn1sBcqFCK9RKig2la+kPnqSVRv06NULflyAcvKOJK8e69yPcqkJ7z1JwF5/aZk XOxX5Nq7CTIOlV5GywLrRX4EpJJ+z944ONIrXF40uhKh7aQc5a7fU7xuZv4ff8XmRc8f L/mivx7uN8juoQZmtWJwwZAZZh+u6XP4Q4+0OiE1F4Lh9wNFRp0eLq76k8nvebDzjW5W p3lgiJ73GdREb8V8jOD3ZLYQ3ObUd4y9ZQ0WjJF2TEw4zX0Jggguj+a56XGD9ZMsAkl8 OQOw== X-Gm-Message-State: AOAM531WUoShODCLYVgXoW1weA38Qx8dIvaRn0ZYraNpF0X3DMOB3/T1 JIIRuG2bvllXXyqKvtEBY0JpE5ROPGtSGQ== X-Google-Smtp-Source: ABdhPJxJSEY3JpYapPyJgRFfb6CcKqkYiNmE8ZVIUlkh0Y3kcaCulBxV1MAVNYwO8FmVlhRD8liyUA== X-Received: by 2002:a17:902:9a4b:: with SMTP id x11mr6512647plv.255.1594966895386; Thu, 16 Jul 2020 23:21:35 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([117.210.211.74]) by smtp.gmail.com with ESMTPSA id b4sm6630466pfo.137.2020.07.16.23.21.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Jul 2020 23:21:34 -0700 (PDT) From: Sumit Garg To: daniel.thompson@linaro.org Cc: patches@linaro.org, Sumit Garg Subject: [RFC INTERNAL v3 4/4] serial: amba-pl011: Enable NMI aware polling mode Date: Fri, 17 Jul 2020 11:50:57 +0530 Message-Id: <1594966857-5215-5-git-send-email-sumit.garg@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> References: <1594966857-5215-1-git-send-email-sumit.garg@linaro.org> Allow serial interrupt to be requested as an NMI in polling mode. Currently this NMI aware polling mode only supports NMI driven RX and TX data. DMA operation isn't supported. Also, while operating in NMI mode, RX always remains active irrespective of whether corresponding TTY port is active or not. So we directly bail out of startup, shutdown and rx_stop APIs if NMI mode is active. Signed-off-by: Sumit Garg --- drivers/tty/serial/amba-pl011.c | 128 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 117 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 0983c5e..36c32b8 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include "amba-pl011.h" @@ -347,6 +349,10 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) if (uart_handle_sysrq_char(&uap->port, ch & 255)) continue; + if (uart_nmi_handle_char(&uap->port, ch, UART011_DR_OE, ch, + flag)) + continue; + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); } @@ -1316,6 +1322,9 @@ static void pl011_stop_rx(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM| UART011_PEIM|UART011_BEIM|UART011_OEIM); pl011_write(uap->im, uap, REG_IMSC); @@ -1604,13 +1613,6 @@ static int pl011_hwinit(struct uart_port *port) UART011_FEIS | UART011_RTIS | UART011_RXIS, uap, REG_ICR); - /* - * Save interrupts enable mask, and enable RX interrupts in case if - * the interrupt is used for NMI entry. - */ - uap->im = pl011_read(uap, REG_IMSC); - pl011_write(UART011_RTIM | UART011_RXIM, uap, REG_IMSC); - if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -1711,6 +1713,100 @@ static void pl011_put_poll_char(struct uart_port *port, pl011_write(ch, uap, REG_DR); } +static void pl011_nmi_rx_chars(struct uart_amba_port *uap) +{ + pl011_fifo_to_tty(uap); + irq_work_queue(&uap->port.nmi_state.rx_work); +} + +static irqreturn_t pl011_nmi_int(int irq, void *dev_id) +{ + struct uart_amba_port *uap = dev_id; + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + int handled = 0; + + status = pl011_read(uap, REG_MIS); + if (status) { + do { + check_apply_cts_event_workaround(uap); + + pl011_write(status, uap, REG_ICR); + + if (status & (UART011_RTIS|UART011_RXIS)) + pl011_nmi_rx_chars(uap); + + if (status & UART011_TXIS) + irq_work_queue(&uap->port.nmi_state.tx_work); + + if (pass_counter-- == 0) + break; + + status = pl011_read(uap, REG_MIS); + } while (status != 0); + handled = 1; + } + + return IRQ_RETVAL(handled); +} + +static int pl011_allocate_nmi(struct uart_amba_port *uap) +{ + int ret; + + irq_set_status_flags(uap->port.irq, IRQ_NOAUTOEN); + ret = request_nmi(uap->port.irq, pl011_nmi_int, IRQF_PERCPU, + "uart-pl011", uap); + if (ret) { + irq_clear_status_flags(uap->port.irq, IRQ_NOAUTOEN); + return ret; + } + + enable_irq(uap->port.irq); + + return ret; +} + +static void pl011_tx_irq_callback(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + + spin_lock(&port->lock); + pl011_tx_chars(uap, true); + spin_unlock(&port->lock); +} + +static int pl011_poll_init(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + int retval; + + retval = pl011_hwinit(port); + if (retval) + goto clk_dis; + + /* In case NMI isn't supported, fallback to normal interrupt mode */ + retval = pl011_allocate_nmi(uap); + if (retval) + return 0; + + retval = uart_nmi_state_init(port); + if (retval) + goto clk_dis; + + port->nmi_state.tx_irq_callback = pl011_tx_irq_callback; + uart_set_nmi_active(port, true); + + pl011_enable_interrupts(uap); + + return 0; + + clk_dis: + clk_disable_unprepare(uap->clk); + return retval; +} + #endif /* CONFIG_CONSOLE_POLL */ static bool pl011_split_lcrh(const struct uart_amba_port *uap) @@ -1736,8 +1832,6 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h) static int pl011_allocate_irq(struct uart_amba_port *uap) { - pl011_write(uap->im, uap, REG_IMSC); - return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap); } @@ -1748,6 +1842,9 @@ static int pl011_startup(struct uart_port *port) unsigned int cr; int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) goto clk_dis; @@ -1790,6 +1887,9 @@ static int sbsa_uart_startup(struct uart_port *port) container_of(port, struct uart_amba_port, port); int retval; + if (uart_nmi_active(port)) + return 0; + retval = pl011_hwinit(port); if (retval) return retval; @@ -1859,6 +1959,9 @@ static void pl011_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); pl011_dma_shutdown(uap); @@ -1891,6 +1994,9 @@ static void sbsa_uart_shutdown(struct uart_port *port) struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + if (uart_nmi_active(port)) + return; + pl011_disable_interrupts(uap); free_irq(uap->port.irq, uap); @@ -2142,7 +2248,7 @@ static const struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif @@ -2173,7 +2279,7 @@ static const struct uart_ops sbsa_uart_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL - .poll_init = pl011_hwinit, + .poll_init = pl011_poll_init, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif