Commit f3974413 authored by Akash Asthana's avatar Akash Asthana Committed by Greg Kroah-Hartman
Browse files

tty: serial: qcom_geni_serial: Wakeup IRQ cleanup

This patch is the continuation of below mentioned commits which adds wakeup
feature over the UART RX line.
1)commit 3e4aaea7 ("tty: serial: qcom_geni_serial: IRQ cleanup")[v2]
2)commit 8b7103f3 ("tty: serial: qcom_geni_serial: Wakeup over UART
  RX")[v2]

The following cleanup is done based on upstream comment received on
subsequent versions of the above-mentioned commits to simplifying the code.
 - Use devm_kasprintf API in place of scnprintf.
 - Use dev_pm_set_dedicated_wake_irq API that will take care of
   requesting and attaching wakeup irqs for devices. Also, it sets wakeirq
   status to WAKE_IRQ_DEDICATED_ALLOCATED as a result enabling/disabling of
   wake irq will be managed by suspend/resume framework. We can remove the
   code for enabling and disabling of wake irq from the this driver.
 - Use platform_get_irq_optional API to get optional wakeup IRQ for
   device.
 - Move ISR registration later in probe after uart port gets register with
   serial core.

Patch link:
 - https://patchwork.kernel.org/patch/11189717/ (v3)
 - https://patchwork.kernel.org/patch/11227435/ (v4)
 - https://patchwork.kernel.org/patch/11241669/ (v5)
 - https://patchwork.kernel.org/patch/11258045/

 (v6)

Signed-off-by: default avatarAkash Asthana <akashast@codeaurora.org>
Reviewed-by: default avatarMatthias Kaehlcke <mka@chromium.org>
Reviewed-by: default avatarStephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/1578321905-25843-2-git-send-email-akashast@codeaurora.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b2097131
Loading
Loading
Loading
Loading
+43 −48
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>
#include <linux/pm_wakeirq.h>
#include <linux/qcom-geni-se.h>
#include <linux/qcom-geni-se.h>
#include <linux/serial.h>
#include <linux/serial.h>
@@ -99,7 +100,7 @@
struct qcom_geni_serial_port {
struct qcom_geni_serial_port {
	struct uart_port uport;
	struct uart_port uport;
	struct geni_se se;
	struct geni_se se;
	char name[20];
	const char *name;
	u32 tx_fifo_depth;
	u32 tx_fifo_depth;
	u32 tx_fifo_width;
	u32 tx_fifo_width;
	u32 rx_fifo_depth;
	u32 rx_fifo_depth;
@@ -753,15 +754,6 @@ out_write_wakeup:
		uart_write_wakeup(uport);
		uart_write_wakeup(uport);
}
}


static irqreturn_t qcom_geni_serial_wakeup_isr(int isr, void *dev)
{
	struct uart_port *uport = dev;

	pm_wakeup_event(uport->dev, 2000);

	return IRQ_HANDLED;
}

static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
{
{
	u32 m_irq_en;
	u32 m_irq_en;
@@ -1298,51 +1290,59 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
	port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
	port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;
	port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;
	port->tx_fifo_width = DEF_FIFO_WIDTH_BITS;


	scnprintf(port->name, sizeof(port->name), "qcom_geni_serial_%s%d",
	port->name = devm_kasprintf(uport->dev, GFP_KERNEL,
		(uart_console(uport) ? "console" : "uart"), uport->line);
			"qcom_geni_serial_%s%d",
			uart_console(uport) ? "console" : "uart", uport->line);
	if (!port->name)
		return -ENOMEM;

	irq = platform_get_irq(pdev, 0);
	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
	if (irq < 0)
		return irq;
		return irq;
	uport->irq = irq;
	uport->irq = irq;
	uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE);
	uport->has_sysrq = IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE);


	if (!console)
		port->wakeup_irq = platform_get_irq_optional(pdev, 1);

	uport->private_data = drv;
	platform_set_drvdata(pdev, port);
	port->handle_rx = console ? handle_rx_console : handle_rx_uart;
	if (!console)
		device_create_file(uport->dev, &dev_attr_loopback);

	ret = uart_add_one_port(drv, uport);
	if (ret)
		return ret;

	irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
	irq_set_status_flags(uport->irq, IRQ_NOAUTOEN);
	ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
	ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr,
			IRQF_TRIGGER_HIGH, port->name, uport);
			IRQF_TRIGGER_HIGH, port->name, uport);
	if (ret) {
	if (ret) {
		dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
		dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret);
		uart_remove_one_port(drv, uport);
		return ret;
		return ret;
	}
	}


	if (!console) {
	/*
		port->wakeup_irq = platform_get_irq(pdev, 1);
	 * Set pm_runtime status as ACTIVE so that wakeup_irq gets
		if (port->wakeup_irq < 0) {
	 * enabled/disabled from dev_pm_arm_wake_irq during system
			dev_err(&pdev->dev, "Failed to get wakeup IRQ %d\n",
	 * suspend/resume respectively.
	 */
	pm_runtime_set_active(&pdev->dev);

	if (port->wakeup_irq > 0) {
		device_init_wakeup(&pdev->dev, true);
		ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
						port->wakeup_irq);
						port->wakeup_irq);
		} else {
			irq_set_status_flags(port->wakeup_irq, IRQ_NOAUTOEN);
			ret = devm_request_irq(uport->dev, port->wakeup_irq,
				qcom_geni_serial_wakeup_isr,
				IRQF_TRIGGER_FALLING, "uart_wakeup", uport);
		if (ret) {
		if (ret) {
				dev_err(uport->dev, "Failed to register wakeup IRQ ret %d\n",
			device_init_wakeup(&pdev->dev, false);
						ret);
			uart_remove_one_port(drv, uport);
			return ret;
			return ret;
		}
		}

			device_init_wakeup(&pdev->dev, true);
			ret = dev_pm_set_wake_irq(&pdev->dev, port->wakeup_irq);
			if (unlikely(ret))
				dev_err(uport->dev, "%s:Failed to set IRQ wake:%d\n",
						__func__, ret);
		}
	}
	}
	uport->private_data = drv;

	platform_set_drvdata(pdev, port);
	return 0;
	port->handle_rx = console ? handle_rx_console : handle_rx_uart;
	if (!console)
		device_create_file(uport->dev, &dev_attr_loopback);
	return uart_add_one_port(drv, uport);
}
}


static int qcom_geni_serial_remove(struct platform_device *pdev)
static int qcom_geni_serial_remove(struct platform_device *pdev)
@@ -1350,7 +1350,10 @@ static int qcom_geni_serial_remove(struct platform_device *pdev)
	struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
	struct qcom_geni_serial_port *port = platform_get_drvdata(pdev);
	struct uart_driver *drv = port->uport.private_data;
	struct uart_driver *drv = port->uport.private_data;


	dev_pm_clear_wake_irq(&pdev->dev);
	device_init_wakeup(&pdev->dev, false);
	uart_remove_one_port(drv, &port->uport);
	uart_remove_one_port(drv, &port->uport);

	return 0;
	return 0;
}
}


@@ -1359,12 +1362,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
	struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
	struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
	struct uart_port *uport = &port->uport;
	struct uart_port *uport = &port->uport;


	uart_suspend_port(uport->private_data, uport);
	return uart_suspend_port(uport->private_data, uport);

	if (port->wakeup_irq > 0)
		enable_irq(port->wakeup_irq);

	return 0;
}
}


static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
@@ -1372,9 +1370,6 @@ static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
	struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
	struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
	struct uart_port *uport = &port->uport;
	struct uart_port *uport = &port->uport;


	if (port->wakeup_irq > 0)
		disable_irq(port->wakeup_irq);

	return uart_resume_port(uport->private_data, uport);
	return uart_resume_port(uport->private_data, uport);
}
}