mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
serial: msm_geni_serial: Allow clock_on/off ioctl to be optional
Add support in the driver to manage power without enabling pm runtime. UART driver gives control to user space client to vote for clock on/off by exposing ioctls. These vote clock on/off APIs depend on PM runtime framework for power related operations. This change relaxes driver from depending on userspace ioctls to invoke runtime resume/suspend for basic uart functionality which will now be done by system suspend/resume. This will block PM framework API's and use system suspend/resume API for UART on/off. Change-Id: Idf0632c0e2d40907f7a226cd7e3e814d1c1f6751 Signed-off-by: Ashish Kori <akori@codeaurora.org>
This commit is contained in:
parent
a9eb6ca4c9
commit
790ab2f4d7
1 changed files with 70 additions and 16 deletions
|
|
@ -206,6 +206,7 @@ struct msm_geni_serial_port {
|
|||
struct completion m_cmd_timeout;
|
||||
struct completion s_cmd_timeout;
|
||||
spinlock_t rx_lock;
|
||||
bool pm_auto_suspend_disable;
|
||||
};
|
||||
|
||||
static const struct uart_ops msm_geni_serial_pops;
|
||||
|
|
@ -531,8 +532,12 @@ static int vote_clock_off(struct uart_port *uport)
|
|||
static int msm_geni_serial_ioctl(struct uart_port *uport, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
|
||||
int ret = -ENOIOCTLCMD;
|
||||
|
||||
if (port->pm_auto_suspend_disable)
|
||||
return ret;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCPMGET:
|
||||
case MSM_GENI_SERIAL_TIOCPMGET: {
|
||||
|
|
@ -709,8 +714,11 @@ static void msm_geni_serial_power_off(struct uart_port *uport)
|
|||
__func__);
|
||||
return;
|
||||
}
|
||||
pm_runtime_mark_last_busy(uport->dev);
|
||||
pm_runtime_put_autosuspend(uport->dev);
|
||||
|
||||
if (pm_runtime_enabled(uport->dev)) {
|
||||
pm_runtime_mark_last_busy(uport->dev);
|
||||
pm_runtime_put_autosuspend(uport->dev);
|
||||
}
|
||||
}
|
||||
|
||||
static int msm_geni_serial_poll_bit(struct uart_port *uport,
|
||||
|
|
@ -1167,7 +1175,7 @@ static void msm_geni_serial_start_tx(struct uart_port *uport)
|
|||
goto exit_start_tx;
|
||||
}
|
||||
|
||||
if (!uart_console(uport)) {
|
||||
if (!uart_console(uport) && pm_runtime_enabled(uport->dev)) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_misc,
|
||||
"%s.Power on.\n", __func__);
|
||||
pm_runtime_get(uport->dev);
|
||||
|
|
@ -2207,6 +2215,9 @@ static void msm_geni_serial_shutdown(struct uart_port *uport)
|
|||
msm_geni_serial_stop_tx(uport);
|
||||
}
|
||||
|
||||
if (msm_port->pm_auto_suspend_disable)
|
||||
disable_irq(uport->irq);
|
||||
|
||||
if (!uart_console(uport)) {
|
||||
if (msm_port->ioctl_count) {
|
||||
int i;
|
||||
|
|
@ -2220,10 +2231,12 @@ static void msm_geni_serial_shutdown(struct uart_port *uport)
|
|||
msm_port->ioctl_count = 0;
|
||||
}
|
||||
|
||||
ret = pm_runtime_put_sync_suspend(uport->dev);
|
||||
if (ret) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_pwr,
|
||||
"%s: Failed to suspend:%d\n", __func__, ret);
|
||||
if (pm_runtime_enabled(uport->dev)) {
|
||||
ret = pm_runtime_put_sync_suspend(uport->dev);
|
||||
if (ret) {
|
||||
IPC_LOG_MSG(msm_port->ipc_log_pwr,
|
||||
"%s: Failed to suspend:%d\n", __func__, ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (msm_port->wakeup_irq > 0) {
|
||||
|
|
@ -2371,7 +2384,7 @@ static int msm_geni_serial_startup(struct uart_port *uport)
|
|||
* and disabled in runtime_suspend to avoid spurious interrupts
|
||||
* after suspend.
|
||||
*/
|
||||
if (uart_console(uport))
|
||||
if (uart_console(uport) || msm_port->pm_auto_suspend_disable)
|
||||
enable_irq(uport->irq);
|
||||
|
||||
if (msm_port->wakeup_irq > 0) {
|
||||
|
|
@ -2842,9 +2855,32 @@ static void msm_geni_serial_cons_pm(struct uart_port *uport,
|
|||
{
|
||||
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
|
||||
|
||||
if (unlikely(!uart_console(uport)))
|
||||
if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
|
||||
se_geni_resources_on(&msm_port->serial_rsc);
|
||||
else if (new_state == UART_PM_STATE_OFF &&
|
||||
old_state == UART_PM_STATE_ON)
|
||||
se_geni_resources_off(&msm_port->serial_rsc);
|
||||
}
|
||||
|
||||
static void msm_geni_serial_hs_pm(struct uart_port *uport,
|
||||
unsigned int new_state, unsigned int old_state)
|
||||
{
|
||||
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
|
||||
|
||||
/*
|
||||
* This will get call for system suspend/resume and
|
||||
* Applicable for hs-uart without runtime pm framework support.
|
||||
*/
|
||||
if (pm_runtime_enabled(uport->dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Default PM State is UNDEFINED Setting it to OFF State.
|
||||
* This will allow add one port to do resources on and off during probe
|
||||
*/
|
||||
if (old_state == UART_PM_STATE_UNDEFINED)
|
||||
old_state = UART_PM_STATE_OFF;
|
||||
|
||||
if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF)
|
||||
se_geni_resources_on(&msm_port->serial_rsc);
|
||||
else if (new_state == UART_PM_STATE_OFF &&
|
||||
|
|
@ -2886,6 +2922,8 @@ static const struct uart_ops msm_geni_serial_pops = {
|
|||
.break_ctl = msm_geni_serial_break_ctl,
|
||||
.flush_buffer = NULL,
|
||||
.ioctl = msm_geni_serial_ioctl,
|
||||
/* For HSUART nodes without IOCTL support */
|
||||
.pm = msm_geni_serial_hs_pm,
|
||||
};
|
||||
|
||||
static const struct of_device_id msm_geni_device_tbl[] = {
|
||||
|
|
@ -3217,6 +3255,14 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
|
|||
|
||||
uport->private_data = (void *)drv;
|
||||
platform_set_drvdata(pdev, dev_port);
|
||||
/*
|
||||
* To Disable PM runtime API that will make ioctl based
|
||||
* vote_clock_on/off optional and rely on system PM
|
||||
*/
|
||||
dev_port->pm_auto_suspend_disable =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,auto-suspend-disable");
|
||||
|
||||
if (is_console) {
|
||||
dev_port->handle_rx = handle_rx_console;
|
||||
dev_port->rx_fifo = devm_kzalloc(uport->dev, sizeof(u32),
|
||||
|
|
@ -3226,10 +3272,15 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
|
|||
dev_port->rx_fifo = devm_kzalloc(uport->dev,
|
||||
sizeof(dev_port->rx_fifo_depth * sizeof(u32)),
|
||||
GFP_KERNEL);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 150);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
if (dev_port->pm_auto_suspend_disable) {
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_forbid(&pdev->dev);
|
||||
} else {
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 150);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING) &&
|
||||
|
|
@ -3290,6 +3341,8 @@ static int msm_geni_serial_remove(struct platform_device *pdev)
|
|||
|
||||
if (!uart_console(&port->uport))
|
||||
wakeup_source_unregister(port->geni_wake);
|
||||
if (port->pm_auto_suspend_disable)
|
||||
pm_runtime_allow(&pdev->dev);
|
||||
uart_remove_one_port(drv, &port->uport);
|
||||
if (port->rx_dma) {
|
||||
geni_se_iommu_free_buf(port->wrapper_dev, &port->rx_dma,
|
||||
|
|
@ -3416,7 +3469,7 @@ static int msm_geni_serial_sys_suspend(struct device *dev)
|
|||
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *uport = &port->uport;
|
||||
|
||||
if (uart_console(uport)) {
|
||||
if (uart_console(uport) || port->pm_auto_suspend_disable) {
|
||||
uart_suspend_port((struct uart_driver *)uport->private_data,
|
||||
uport);
|
||||
} else {
|
||||
|
|
@ -3445,8 +3498,9 @@ static int msm_geni_serial_sys_resume(struct device *dev)
|
|||
struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
|
||||
struct uart_port *uport = &port->uport;
|
||||
|
||||
if (uart_console(uport) &&
|
||||
console_suspend_enabled && uport->suspended) {
|
||||
if ((uart_console(uport) &&
|
||||
console_suspend_enabled && uport->suspended) ||
|
||||
port->pm_auto_suspend_disable) {
|
||||
uart_resume_port((struct uart_driver *)uport->private_data,
|
||||
uport);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue