Skip to content

Commit

Permalink
drivers: msm_serial_hs: Update driver from 32.1.F.0.x
Browse files Browse the repository at this point in the history
Signed-off-by: Humberto Borba <humberos@gmail.com>
Change-Id: Ic840dc855bd6ec0cd0b863d76895e066ae2c9564
  • Loading branch information
humberos committed Mar 26, 2016
1 parent 0d5d4bb commit 529ec81
Showing 1 changed file with 77 additions and 31 deletions.
108 changes: 77 additions & 31 deletions drivers/tty/serial/msm_serial_hs.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <linux/ipc_logging.h>
#include <asm/irq.h>
#include <linux/kthread.h>
#include <linux/delay.h>

#include <linux/msm-sps.h>
#include <linux/platform_data/msm_serial_hs.h>
Expand Down Expand Up @@ -210,6 +211,7 @@ struct msm_hs_wakeup {
unsigned char rx_to_inject;
bool enabled;
bool freed;
struct work_struct resume_work;
};

struct msm_hs_port {
Expand Down Expand Up @@ -255,6 +257,7 @@ struct msm_hs_port {
atomic_t ioctl_count;
bool obs; /* out of band sleep flag */
atomic_t client_req_state;
atomic_t wakeup_irq_disabled;
};

static struct of_device_id msm_hs_match_table[] = {
Expand Down Expand Up @@ -1180,6 +1183,10 @@ static void msm_hs_set_termios(struct uart_port *uport,
* UART Core would trigger RFR if it is not having any space with
* RX FIFO.
*/
#ifndef CONFIG_BT_MSM_SLEEP
/* Pulling RFR line high */
msm_hs_write(uport, UART_DM_CR, RFR_LOW);
#endif
data = msm_hs_read(uport, UART_DM_MR1);
data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
if (c_cflag & CRTSCTS) {
Expand Down Expand Up @@ -1987,8 +1994,8 @@ void msm_hs_set_mctrl(struct uart_port *uport,
unsigned int mctrl)
{
unsigned long flags;

struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);

#ifdef CONFIG_BT_MSM_SLEEP
if (msm_uport->pm_state != MSM_HS_PM_ACTIVE) {
MSM_HS_WARN("%s(): Failed.Clocks are OFF\n", __func__);
Expand Down Expand Up @@ -2190,12 +2197,22 @@ void toggle_wakeup_interrupt(struct msm_hs_port *msm_uport)
spin_lock_irqsave(&uport->lock, flags);
msm_uport->wakeup.ignore = 1;
MSM_HS_DBG("%s(): Enable Wakeup IRQ", __func__);
atomic_set(&msm_uport->wakeup_irq_disabled, 0);
enable_irq(msm_uport->wakeup.irq);
disable_irq(uport->irq);
msm_uport->wakeup.enabled = true;
spin_unlock_irqrestore(&uport->lock, flags);
} else {
disable_irq_nosync(msm_uport->wakeup.irq);
spin_lock_irqsave(&uport->lock, flags);
if (!atomic_read(&msm_uport->wakeup_irq_disabled)) {
disable_irq_nosync(msm_uport->wakeup.irq);
atomic_inc(&msm_uport->wakeup_irq_disabled);
} else {
MSM_HS_DBG("%s(): wakeup irq has already been disabled",
__func__);
}
spin_unlock_irqrestore(&uport->lock, flags);

enable_irq(uport->irq);
spin_lock_irqsave(&uport->lock, flags);
msm_uport->wakeup.enabled = false;
Expand Down Expand Up @@ -2294,43 +2311,69 @@ EXPORT_SYMBOL(msm_hs_request_clock_on);

static irqreturn_t msm_hs_wakeup_isr(int irq, void *dev)
{
unsigned int wakeup = 0;
unsigned long flags;
struct msm_hs_port *msm_uport = (struct msm_hs_port *)dev;
struct uart_port *uport = &msm_uport->uport;
struct tty_struct *tty = NULL;

msm_hs_resource_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);
if (!atomic_read(&msm_uport->wakeup_irq_disabled)) {
disable_irq_nosync(msm_uport->wakeup.irq);
atomic_inc(&msm_uport->wakeup_irq_disabled);
} else {
MSM_HS_WARN("%s(): wakeup irq has already been disabled",
__func__);
}
spin_unlock_irqrestore(&uport->lock, flags);

MSM_HS_DBG("%s(): ignore %d\n", __func__,
msm_uport->wakeup.ignore);
if (msm_uport->wakeup.ignore)
msm_uport->wakeup.ignore = 0;
else
wakeup = 1;
schedule_work(&msm_uport->wakeup.resume_work);
return IRQ_HANDLED;
}

if (wakeup) {
/*
* Port was clocked off during rx, wake up and
* optionally inject char into tty rx
*/
if (msm_uport->wakeup.inject_rx) {
tty = uport->state->port.tty;
tty_insert_flip_char(tty->port,
msm_uport->wakeup.rx_to_inject,
TTY_NORMAL);
MSM_HS_DBG("%s(): Inject 0x%x", __func__,
msm_uport->wakeup.rx_to_inject);
static void msm_hs_wakeup_resume_work(struct work_struct *work)
{
unsigned int wakeup = 0;
unsigned long flags;
struct msm_hs_port *msm_uport =
container_of(work, struct msm_hs_port,
wakeup.resume_work);
struct uart_port *uport = &msm_uport->uport;
struct tty_struct *tty = NULL;

if (pm_runtime_enabled(uport->dev)) {
msm_hs_resource_vote(msm_uport);
spin_lock_irqsave(&uport->lock, flags);

MSM_HS_DBG("%s(): ignore %d\n", __func__,
msm_uport->wakeup.ignore);
if (msm_uport->wakeup.ignore)
msm_uport->wakeup.ignore = 0;
else
wakeup = 1;

if (wakeup) {
/*
* Port was clocked off during rx, wake up and
* optionally inject char into tty rx
*/
if (msm_uport->wakeup.inject_rx) {
tty = uport->state->port.tty;
tty_insert_flip_char(tty->port,
msm_uport->wakeup.rx_to_inject,
TTY_NORMAL);
MSM_HS_DBG("%s(): Inject 0x%x", __func__,
msm_uport->wakeup.rx_to_inject);
}
}
}

spin_unlock_irqrestore(&uport->lock, flags);
msm_hs_resource_unvote(msm_uport);
spin_unlock_irqrestore(&uport->lock, flags);
msm_hs_resource_unvote(msm_uport);

if (wakeup && msm_uport->wakeup.inject_rx)
tty_flip_buffer_push(tty->port);
return IRQ_HANDLED;
if (wakeup && msm_uport->wakeup.inject_rx)
tty_flip_buffer_push(tty->port);
} else {
usleep(100);
schedule_work(&msm_uport->wakeup.resume_work);
}
}

static const char *msm_hs_type(struct uart_port *port)
Expand Down Expand Up @@ -2517,7 +2560,7 @@ static int msm_hs_startup(struct uart_port *uport)
if (is_use_low_power_wakeup(msm_uport)) {
ret = request_threaded_irq(msm_uport->wakeup.irq, NULL,
msm_hs_wakeup_isr,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"msm_hs_wakeup", msm_uport);
if (unlikely(ret)) {
MSM_HS_ERR("%s():Err getting uart wakeup_irq %d\n",
Expand Down Expand Up @@ -2635,6 +2678,7 @@ static int msm_hs_startup(struct uart_port *uport)
spin_lock_irqsave(&uport->lock, flags);
atomic_set(&msm_uport->ioctl_count, 0);
atomic_set(&msm_uport->client_req_state, 0);
atomic_set(&msm_uport->wakeup_irq_disabled, 0);
msm_hs_start_rx_locked(uport);

spin_unlock_irqrestore(&uport->lock, flags);
Expand Down Expand Up @@ -3164,7 +3208,7 @@ static void msm_serial_hs_rt_init(struct uart_port *uport)

MSM_HS_INFO("%s(): Enabling runtime pm", __func__);
pm_runtime_set_suspended(uport->dev);
pm_runtime_set_autosuspend_delay(uport->dev, 100);
pm_runtime_set_autosuspend_delay(uport->dev, 5000);
pm_runtime_use_autosuspend(uport->dev);
mutex_lock(&msm_uport->mtx);
msm_uport->pm_state = MSM_HS_PM_SUSPENDED;
Expand Down Expand Up @@ -3314,6 +3358,7 @@ static int msm_hs_probe(struct platform_device *pdev)
msm_uport->wakeup.inject_rx = pdata->inject_rx_on_wakeup;
msm_uport->wakeup.rx_to_inject = pdata->rx_to_inject;
msm_uport->obs = pdata->obs;
INIT_WORK(&msm_uport->wakeup.resume_work, msm_hs_wakeup_resume_work);

msm_uport->bam_tx_ep_pipe_index =
pdata->bam_tx_ep_pipe_index;
Expand Down Expand Up @@ -3515,6 +3560,7 @@ static void msm_hs_shutdown(struct uart_port *uport)
__func__);
}

cancel_work_sync(&msm_uport->wakeup.resume_work);
cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
flush_workqueue(msm_uport->hsuart_wq);

Expand Down

0 comments on commit 529ec81

Please sign in to comment.