summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/omap-serial.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-09-20 13:19:32 -0700
committerOlof Johansson <olof@lixom.net>2012-09-20 13:22:20 -0700
commit2843c7d2c03da38dfb14102254d0c767d2483349 (patch)
tree8698671fd889ed9d6237cf9ea093e8bb1fc999b3 /drivers/tty/serial/omap-serial.c
parent084cfebc03ede864835594181210b501aa9f1933 (diff)
parent6bfc82ff589a00e5fbc12b958c649d703d273c86 (diff)
Merge tag 'omap-devel-dt-merged-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/dt
Device tree related changes for omaps. Note that this branch is based on omap-cleanup-sparseirq-for-v3.7 to avoid merge conflicts with the sparseirq changes for gpio-twl4030 driver. * tag 'omap-devel-dt-merged-for-v3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: arm/dts: Mux uart pins for omap4-sdp ARM: OMAP2+: select PINCTRL in Kconfig arm/dts: Add pinctrl driver entries for omap2/3/4 arm/dts: Add omap36xx.dtsi file and rename omap3-beagle to omap3-beagle-xm ARM: dts: omap3-overo: Add support for the blue LED Documentation: dt: Update the OMAP documentation with Overo/Toby ARM: dts: OMAP3: Add support for Gumstix Overo with Tobi expansion board ARM: dts: OMAP4: Add reg and interrupts for every nodes ARM: dts: AM33XX: Specify reg and interrupt property for all nodes ARM: dts: AM33XX: Convert all hex numbers to lower-case ARM: dts: omap3-beagle: Enable audio support ARM: dts: omap5: Add McPDM and DMIC section to the dtsi file ARM: dts: omap5: Add McBSP entries ARM: dts: omap4: Add reg-names for McPDM and DMIC ARM: dts: omap4: Add McBSP entries ARM: dts: omap3: Add McBSP entries ARM: dts: omap2420-h4: Include omap2420.dtsi file instead the common omap2 ARM: dts: omap2: Add McBSP entries for OMAP2420 and OMAP2430 SoC ARM: dts: omap3-beagle: Add heartbeat and mmc LEDs support ARM: dts: omap3: Add gpio-twl4030 properties for BeagleBoard and omap3-EVM ...
Diffstat (limited to 'drivers/tty/serial/omap-serial.c')
-rw-r--r--drivers/tty/serial/omap-serial.c860
1 files changed, 363 insertions, 497 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d3cda0cb2df..f175385bb30 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -32,16 +32,16 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
-#include <plat/dma.h>
-#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
@@ -57,8 +57,8 @@
#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
/* FCR register bitmasks */
-#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
+#define OMAP_UART_FCR_TX_FIFO_TRIG_MASK (0x3 << 4)
/* MVR register bitmasks */
#define OMAP_UART_MVR_SCHEME_SHIFT 30
@@ -71,12 +71,52 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
+struct uart_omap_port {
+ struct uart_port port;
+ struct uart_omap_dma uart_dma;
+ struct device *dev;
+
+ unsigned char ier;
+ unsigned char lcr;
+ unsigned char mcr;
+ unsigned char fcr;
+ unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mdr1;
+ unsigned char scr;
+
+ int use_dma;
+ /*
+ * 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.
+ */
+ unsigned int lsr_break_flag;
+ unsigned char msr_saved_flags;
+ char name[20];
+ unsigned long port_activity;
+ u32 context_loss_cnt;
+ u32 errata;
+ u8 wakeups_enabled;
+ unsigned int irq_pending:1;
+
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_active;
+
+ struct pm_qos_request pm_qos_request;
+ u32 latency;
+ u32 calc_latency;
+ struct work_struct qos_work;
+ struct pinctrl *pins;
+};
+
+#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rxdma_poll(unsigned long uart_no);
-static int serial_omap_start_rxdma(struct uart_omap_port *up);
static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
static struct workqueue_struct *serial_omap_uart_wq;
@@ -101,6 +141,46 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
serial_out(up, UART_FCR, 0);
}
+static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->get_context_loss_count)
+ return 0;
+
+ return pdata->get_context_loss_count(up->dev);
+}
+
+static void serial_omap_set_forceidle(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->set_forceidle)
+ return;
+
+ pdata->set_forceidle(up->dev);
+}
+
+static void serial_omap_set_noidle(struct uart_omap_port *up)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->set_noidle)
+ return;
+
+ pdata->set_noidle(up->dev);
+}
+
+static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
+{
+ struct omap_uart_port_info *pdata = up->dev->platform_data;
+
+ if (!pdata || !pdata->enable_wakeup)
+ return;
+
+ pdata->enable_wakeup(up->dev, enable);
+}
+
/*
* serial_omap_get_divisor - calculate divisor value
* @port: uart port info
@@ -126,151 +206,55 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
return port->uartclk/(baud * divisor);
}
-static void serial_omap_stop_rxdma(struct uart_omap_port *up)
-{
- if (up->uart_dma.rx_dma_used) {
- del_timer(&up->uart_dma.rx_timer);
- omap_stop_dma(up->uart_dma.rx_dma_channel);
- omap_free_dma(up->uart_dma.rx_dma_channel);
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_used = false;
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- }
-}
-
static void serial_omap_enable_ms(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_tx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- if (up->use_dma &&
- up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
- /*
- * Check if dma is still active. If yes do nothing,
- * return. Else stop dma
- */
- if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
- return;
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- omap_free_dma(up->uart_dma.tx_dma_channel);
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- }
-
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
if (up->ier & UART_IER_THRI) {
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
- if (!up->use_dma && pdata && pdata->set_forceidle)
- pdata->set_forceidle(up->pdev);
+ serial_omap_set_forceidle(up);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_stop_rx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(&up->pdev->dev);
- if (up->use_dma)
- serial_omap_stop_rxdma(up);
+ pm_runtime_get_sync(up->dev);
up->ier &= ~UART_IER_RLSI;
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
-}
-
-static inline void receive_chars(struct uart_omap_port *up,
- unsigned int *status)
-{
- struct tty_struct *tty = up->port.state->port.tty;
- unsigned int flag, lsr = *status;
- unsigned char ch = 0;
- int max_count = 256;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_in(up, UART_RX);
- flag = TTY_NORMAL;
- up->port.icount.rx++;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- /*
- * For statistics only
- */
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- up->port.icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(&up->port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE) {
- up->port.icount.parity++;
- } else if (lsr & UART_LSR_FE) {
- up->port.icount.frame++;
- }
-
- if (lsr & UART_LSR_OE)
- up->port.icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_OMAP_CONSOLE
- if (up->port.line == up->port.cons->index) {
- /* Recover the break flag from console xmit */
- lsr |= up->lsr_break_flag;
- }
-#endif
- if (lsr & UART_LSR_BI)
- flag = TTY_BREAK;
- else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
-
- if (uart_handle_sysrq_char(&up->port, ch))
- goto ignore_char;
- uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
-ignore_char:
- lsr = serial_in(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
- tty_flip_buffer_push(tty);
- spin_lock(&up->port.lock);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
-static void transmit_chars(struct uart_omap_port *up)
+static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
{
struct circ_buf *xmit = &up->port.state->xmit;
int count;
+ if (!(lsr & UART_LSR_THRE))
+ return;
+
if (up->port.x_char) {
serial_out(up, UART_TX, up->port.x_char);
up->port.icount.tx++;
@@ -290,8 +274,11 @@ static void transmit_chars(struct uart_omap_port *up)
break;
} while (--count > 0);
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+ spin_unlock(&up->port.lock);
uart_write_wakeup(&up->port);
+ spin_lock(&up->port.lock);
+ }
if (uart_circ_empty(xmit))
serial_omap_stop_tx(&up->port);
@@ -307,70 +294,13 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
static void serial_omap_start_tx(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
- struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
- struct circ_buf *xmit;
- unsigned int start;
- int ret = 0;
-
- if (!up->use_dma) {
- pm_runtime_get_sync(&up->pdev->dev);
- serial_omap_enable_ier_thri(up);
- if (pdata && pdata->set_noidle)
- pdata->set_noidle(up->pdev);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- return;
- }
-
- if (up->uart_dma.tx_dma_used)
- return;
-
- xmit = &up->port.state->xmit;
-
- if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
- pm_runtime_get_sync(&up->pdev->dev);
- ret = omap_request_dma(up->uart_dma.uart_dma_tx,
- "UART Tx DMA",
- (void *)uart_tx_dma_callback, up,
- &(up->uart_dma.tx_dma_channel));
+ struct uart_omap_port *up = to_uart_omap_port(port);
- if (ret < 0) {
- serial_omap_enable_ier_thri(up);
- return;
- }
- }
- spin_lock(&(up->uart_dma.tx_lock));
- up->uart_dma.tx_dma_used = true;
- spin_unlock(&(up->uart_dma.tx_lock));
-
- start = up->uart_dma.tx_buf_dma_phys +
- (xmit->tail & (UART_XMIT_SIZE - 1));
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys +
- UART_XMIT_SIZE) - start;
-
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
+ pm_runtime_get_sync(up->dev);
+ serial_omap_enable_ier_thri(up);
+ serial_omap_set_noidle(up);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static unsigned int check_modem_status(struct uart_omap_port *up)
@@ -401,76 +331,158 @@ static unsigned int check_modem_status(struct uart_omap_port *up)
return status;
}
+static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
+{
+ unsigned int flag;
+
+ up->port.icount.rx++;
+ flag = TTY_NORMAL;
+
+ if (lsr & UART_LSR_BI) {
+ flag = TTY_BREAK;
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+ up->port.icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ return;
+
+ }
+
+ if (lsr & UART_LSR_PE) {
+ flag = TTY_PARITY;
+ up->port.icount.parity++;
+ }
+
+ if (lsr & UART_LSR_FE) {
+ flag = TTY_FRAME;
+ up->port.icount.frame++;
+ }
+
+ if (lsr & UART_LSR_OE)
+ up->port.icount.overrun++;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+ if (up->port.line == up->port.cons->index) {
+ /* Recover the break flag from console xmit */
+ lsr |= up->lsr_break_flag;
+ }
+#endif
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, 0, flag);
+}
+
+static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
+{
+ unsigned char ch = 0;
+ unsigned int flag;
+
+ if (!(lsr & UART_LSR_DR))
+ return;
+
+ ch = serial_in(up, UART_RX);
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (uart_handle_sysrq_char(&up->port, ch))
+ return;
+
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+}
+
/**
* serial_omap_irq() - This handles the interrupt from one port
* @irq: uart port irq number
* @dev_id: uart port info
*/
-static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+static irqreturn_t serial_omap_irq(int irq, void *dev_id)
{
struct uart_omap_port *up = dev_id;
+ struct tty_struct *tty = up->port.state->port.tty;
unsigned int iir, lsr;
- unsigned long flags;
+ unsigned int type;
+ irqreturn_t ret = IRQ_NONE;
+ int max_count = 256;
- pm_runtime_get_sync(&up->pdev->dev);
- iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT) {
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
- return IRQ_NONE;
- }
+ spin_lock(&up->port.lock);
+ pm_runtime_get_sync(up->dev);
- spin_lock_irqsave(&up->port.lock, flags);
- lsr = serial_in(up, UART_LSR);
- if (iir & UART_IIR_RLSI) {
- if (!up->use_dma) {
- if (lsr & UART_LSR_DR)
- receive_chars(up, &lsr);
- } else {
- up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- if ((serial_omap_start_rxdma(up) != 0) &&
- (lsr & UART_LSR_DR))
- receive_chars(up, &lsr);
+ do {
+ iir = serial_in(up, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ break;
+
+ ret = IRQ_HANDLED;
+ lsr = serial_in(up, UART_LSR);
+
+ /* extract IRQ type from IIR register */
+ type = iir & 0x3e;
+
+ switch (type) {
+ case UART_IIR_MSI:
+ check_modem_status(up);
+ break;
+ case UART_IIR_THRI:
+ transmit_chars(up, lsr);
+ break;
+ case UART_IIR_RX_TIMEOUT:
+ /* FALLTHROUGH */
+ case UART_IIR_RDI:
+ serial_omap_rdi(up, lsr);
+ break;
+ case UART_IIR_RLSI:
+ serial_omap_rlsi(up, lsr);
+ break;
+ case UART_IIR_CTS_RTS_DSR:
+ /* simply try again */
+ break;
+ case UART_IIR_XOFF:
+ /* FALLTHROUGH */
+ default:
+ break;
}
- }
+ } while (!(iir & UART_IIR_NO_INT) && max_count--);
- check_modem_status(up);
- if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
- transmit_chars(up);
+ spin_unlock(&up->port.lock);
- spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ tty_flip_buffer_push(tty);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
- return IRQ_HANDLED;
+
+ return ret;
}
static unsigned int serial_omap_tx_empty(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
unsigned int ret = 0;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
return ret;
}
static unsigned int serial_omap_get_mctrl(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
unsigned int ret = 0;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
status = check_modem_status(up);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
@@ -487,7 +499,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char mcr = 0;
dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
@@ -502,20 +514,31 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
up->mcr = serial_in(up, UART_MCR);
up->mcr |= mcr;
serial_out(up, UART_MCR, up->mcr);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+
+ if (gpio_is_valid(up->DTR_gpio) &&
+ !!(mctrl & TIOCM_DTR) != up->DTR_active) {
+ up->DTR_active = !up->DTR_active;
+ if (gpio_cansleep(up->DTR_gpio))
+ schedule_work(&up->qos_work);
+ else
+ gpio_set_value(up->DTR_gpio,
+ up->DTR_active != up->DTR_inverted);
+ }
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -523,12 +546,13 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_startup(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
int retval;
@@ -542,7 +566,7 @@ static int serial_omap_startup(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
@@ -573,20 +597,6 @@ static int serial_omap_startup(struct uart_port *port)
spin_unlock_irqrestore(&up->port.lock, flags);
up->msr_saved_flags = 0;
- if (up->use_dma) {
- free_page((unsigned long)up->port.state->xmit.buf);
- up->port.state->xmit.buf = dma_alloc_coherent(NULL,
- UART_XMIT_SIZE,
- (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
- 0);
- init_timer(&(up->uart_dma.rx_timer));
- up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
- up->uart_dma.rx_timer.data = up->port.line;
- /* Currently the buffer size is 4KB. Can increase it */
- up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
- up->uart_dma.rx_buf_size,
- (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
- }
/*
* Finally, enable interrupts. Note: Modem status interrupts
* are set via set_termios(), which will be occurring imminently
@@ -598,20 +608,20 @@ static int serial_omap_startup(struct uart_port *port)
/* Enable module level wake up */
serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
return 0;
}
static void serial_omap_shutdown(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
/*
* Disable interrupts from this port
*/
@@ -634,19 +644,9 @@ static void serial_omap_shutdown(struct uart_port *port)
*/
if (serial_in(up, UART_LSR) & UART_LSR_DR)
(void) serial_in(up, UART_RX);
- if (up->use_dma) {
- dma_free_coherent(up->port.dev,
- UART_XMIT_SIZE, up->port.state->xmit.buf,
- up->uart_dma.tx_buf_dma_phys);
- up->port.state->xmit.buf = NULL;
- serial_omap_stop_rx(port);
- dma_free_coherent(up->port.dev,
- up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
- up->uart_dma.rx_buf_dma_phys);
- up->uart_dma.rx_buf = NULL;
- }
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
free_irq(up->port.irq, up);
}
@@ -667,19 +667,19 @@ serial_omap_configure_xonxoff
/*
* IXON Flag:
- * Enable XON/XOFF flow control on output.
- * Transmit XON1, XOFF1
+ * Flow control for OMAP.TX
+ * OMAP.RX should listen for XON/XOFF
*/
if (termios->c_iflag & IXON)
- up->efr |= OMAP_UART_SW_TX;
+ up->efr |= OMAP_UART_SW_RX;
/*
* IXOFF Flag:
- * Enable XON/XOFF flow control on input.
- * Receiver compares XON1, XOFF1.
+ * Flow control for OMAP.RX
+ * OMAP.TX should send XON/XOFF
*/
if (termios->c_iflag & IXOFF)
- up->efr |= OMAP_UART_SW_RX;
+ up->efr |= OMAP_UART_SW_TX;
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
@@ -715,13 +715,16 @@ static void serial_omap_uart_qos_work(struct work_struct *work)
qos_work);
pm_qos_update_request(&up->pm_qos_request, up->latency);
+ if (gpio_is_valid(up->DTR_gpio))
+ gpio_set_value_cansleep(up->DTR_gpio,
+ up->DTR_active != up->DTR_inverted);
}
static void
serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char cval = 0;
unsigned char efr = 0;
unsigned long flags = 0;
@@ -768,14 +771,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
UART_FCR_ENABLE_FIFO;
- if (up->use_dma)
- up->fcr |= UART_FCR_DMA_SELECT;
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/*
@@ -845,14 +846,13 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
- if (up->use_dma) {
- serial_out(up, UART_TI752_TLR, 0);
- up->scr |= UART_FCR_TRIGGER_4;
- } else {
- /* Set receive FIFO threshold to 1 byte */
- up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
- up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
- }
+ /* Set receive FIFO threshold to 16 characters and
+ * transmit FIFO threshold to 16 spaces
+ */
+ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
+ up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
+ up->fcr |= UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 |
+ UART_FCR_ENABLE_FIFO;
serial_out(up, UART_FCR, up->fcr);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -924,20 +924,30 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_omap_configure_xonxoff(up, termios);
spin_unlock_irqrestore(&up->port.lock, flags);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
}
+static int serial_omap_set_wake(struct uart_port *port, unsigned int state)
+{
+ struct uart_omap_port *up = to_uart_omap_port(port);
+
+ serial_omap_enable_wakeup(up, state);
+
+ return 0;
+}
+
static void
serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned char efr;
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -948,14 +958,15 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
- if (!device_may_wakeup(&up->pdev->dev)) {
+ if (!device_may_wakeup(up->dev)) {
if (!state)
- pm_runtime_forbid(&up->pdev->dev);
+ pm_runtime_forbid(up->dev);
else
- pm_runtime_allow(&up->pdev->dev);
+ pm_runtime_allow(up->dev);
}
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static void serial_omap_release_port(struct uart_port *port)
@@ -971,7 +982,7 @@ static int serial_omap_request_port(struct uart_port *port)
static void serial_omap_config_port(struct uart_port *port, int flags)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
up->port.line);
@@ -989,7 +1000,7 @@ serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
static const char *
serial_omap_type(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line);
return up->name;
@@ -1032,26 +1043,33 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
- pm_runtime_put(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
static int serial_omap_poll_get_char(struct uart_port *port)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
unsigned int status;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
status = serial_in(up, UART_LSR);
- if (!(status & UART_LSR_DR))
- return NO_POLL_CHAR;
+ if (!(status & UART_LSR_DR)) {
+ status = NO_POLL_CHAR;
+ goto out;
+ }
status = serial_in(up, UART_RX);
- pm_runtime_put(&up->pdev->dev);
+
+out:
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+
return status;
}
@@ -1065,7 +1083,7 @@ static struct uart_driver serial_omap_reg;
static void serial_omap_console_putchar(struct uart_port *port, int ch)
{
- struct uart_omap_port *up = (struct uart_omap_port *)port;
+ struct uart_omap_port *up = to_uart_omap_port(port);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
@@ -1080,7 +1098,7 @@ serial_omap_console_write(struct console *co, const char *s,
unsigned int ier;
int locked = 1;
- pm_runtime_get_sync(&up->pdev->dev);
+ pm_runtime_get_sync(up->dev);
local_irq_save(flags);
if (up->port.sysrq)
@@ -1114,8 +1132,8 @@ serial_omap_console_write(struct console *co, const char *s,
if (up->msr_saved_flags)
check_modem_status(up);
- pm_runtime_mark_last_busy(&up->pdev->dev);
- pm_runtime_put_autosuspend(&up->pdev->dev);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
if (locked)
spin_unlock(&up->port.lock);
local_irq_restore(flags);
@@ -1179,6 +1197,7 @@ static struct uart_ops serial_omap_pops = {
.shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios,
.pm = serial_omap_pm,
+ .set_wake = serial_omap_set_wake,
.type = serial_omap_type,
.release_port = serial_omap_release_port,
.request_port = serial_omap_request_port,
@@ -1221,150 +1240,7 @@ static int serial_omap_resume(struct device *dev)
}
#endif
-static void serial_omap_rxdma_poll(unsigned long uart_no)
-{
- struct uart_omap_port *up = ui[uart_no];
- unsigned int curr_dma_pos, curr_transmitted_size;
- int ret = 0;
-
- curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
- if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
- (curr_dma_pos == 0)) {
- if (jiffies_to_msecs(jiffies - up->port_activity) <
- up->uart_dma.rx_timeout) {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- } else {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- return;
- }
-
- curr_transmitted_size = curr_dma_pos -
- up->uart_dma.prev_rx_dma_pos;
- up->port.icount.rx += curr_transmitted_size;
- tty_insert_flip_string(up->port.state->port.tty,
- up->uart_dma.rx_buf +
- (up->uart_dma.prev_rx_dma_pos -
- up->uart_dma.rx_buf_dma_phys),
- curr_transmitted_size);
- tty_flip_buffer_push(up->port.state->port.tty);
- up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
- if (up->uart_dma.rx_buf_size +
- up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
- ret = serial_omap_start_rxdma(up);
- if (ret < 0) {
- serial_omap_stop_rxdma(up);
- up->ier |= (UART_IER_RDI | UART_IER_RLSI);
- serial_out(up, UART_IER, up->ier);
- }
- } else {
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- }
- up->port_activity = jiffies;
-}
-
-static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
-{
- return;
-}
-
-static int serial_omap_start_rxdma(struct uart_omap_port *up)
-{
- int ret = 0;
-
- if (up->uart_dma.rx_dma_channel == -1) {
- pm_runtime_get_sync(&up->pdev->dev);
- ret = omap_request_dma(up->uart_dma.uart_dma_rx,
- "UART Rx DMA",
- (void *)uart_rx_dma_callback, up,
- &(up->uart_dma.rx_dma_channel));
- if (ret < 0)
- return ret;
-
- omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC,
- up->uart_dma.rx_buf_dma_phys, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.rx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_rx, 0);
- }
- up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.rx_dma_channel);
- mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_poll_rate));
- up->uart_dma.rx_dma_used = true;
- return ret;
-}
-
-static void serial_omap_continue_tx(struct uart_omap_port *up)
-{
- struct circ_buf *xmit = &up->port.state->xmit;
- unsigned int start = up->uart_dma.tx_buf_dma_phys
- + (xmit->tail & (UART_XMIT_SIZE - 1));
-
- if (uart_circ_empty(xmit))
- return;
-
- up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
- /*
- * It is a circular buffer. See if the buffer has wounded back.
- * If yes it will have to be transferred in two separate dma
- * transfers
- */
- if (start + up->uart_dma.tx_buf_size >=
- up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
- up->uart_dma.tx_buf_size =
- (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
- omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_CONSTANT,
- up->uart_dma.uart_base, 0, 0);
- omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
- OMAP_DMA_AMODE_POST_INC, start, 0, 0);
- omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
- OMAP_DMA_DATA_TYPE_S8,
- up->uart_dma.tx_buf_size, 1,
- OMAP_DMA_SYNC_ELEMENT,
- up->uart_dma.uart_dma_tx, 0);
- /* FIXME: Cache maintenance needed here? */
- omap_start_dma(up->uart_dma.tx_dma_channel);
-}
-
-static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
-{
- struct uart_omap_port *up = (struct uart_omap_port *)data;
- struct circ_buf *xmit = &up->port.state->xmit;
-
- xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
- (UART_XMIT_SIZE - 1);
- up->port.icount.tx += up->uart_dma.tx_buf_size;
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(&up->port);
-
- if (uart_circ_empty(xmit)) {
- spin_lock(&(up->uart_dma.tx_lock));
- serial_omap_stop_tx(&up->port);
- up->uart_dma.tx_dma_used = false;
- spin_unlock(&(up->uart_dma.tx_lock));
- } else {
- omap_stop_dma(up->uart_dma.tx_dma_channel);
- serial_omap_continue_tx(up);
- }
- up->port_activity = jiffies;
- return;
-}
-
-static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
+static void __devinit omap_serial_fill_features_erratas(struct uart_omap_port *up)
{
u32 mvr, scheme;
u16 revision, major, minor;
@@ -1389,7 +1265,7 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
minor = (mvr & OMAP_UART_MVR_MIN_MASK);
break;
default:
- dev_warn(&up->pdev->dev,
+ dev_warn(up->dev,
"Unknown %s revision, defaulting to highest\n",
up->name);
/* highest possible revision */
@@ -1417,7 +1293,7 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
}
}
-static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+static __devinit struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
{
struct omap_uart_port_info *omap_up_info;
@@ -1430,12 +1306,12 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
return omap_up_info;
}
-static int serial_omap_probe(struct platform_device *pdev)
+static int __devinit serial_omap_probe(struct platform_device *pdev)
{
struct uart_omap_port *up;
- struct resource *mem, *irq, *dma_tx, *dma_rx;
+ struct resource *mem, *irq;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
- int ret = -ENOSPC;
+ int ret;
if (pdev->dev.of_node)
omap_up_info = of_get_uart_port_info(&pdev->dev);
@@ -1458,19 +1334,30 @@ static int serial_omap_probe(struct platform_device *pdev)
return -EBUSY;
}
- dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
- if (!dma_rx)
- return -ENXIO;
-
- dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
- if (!dma_tx)
- return -ENXIO;
+ if (gpio_is_valid(omap_up_info->DTR_gpio) &&
+ omap_up_info->DTR_present) {
+ ret = gpio_request(omap_up_info->DTR_gpio, "omap-serial");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(omap_up_info->DTR_gpio,
+ omap_up_info->DTR_inverted);
+ if (ret < 0)
+ return ret;
+ }
up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
- up->pdev = pdev;
+ if (gpio_is_valid(omap_up_info->DTR_gpio) &&
+ omap_up_info->DTR_present) {
+ up->DTR_gpio = omap_up_info->DTR_gpio;
+ up->DTR_inverted = omap_up_info->DTR_inverted;
+ } else
+ up->DTR_gpio = -EINVAL;
+ up->DTR_active = 0;
+
+ up->dev = &pdev->dev;
up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP;
up->port.iotype = UPIO_MEM;
@@ -1492,6 +1379,13 @@ static int serial_omap_probe(struct platform_device *pdev)
goto err_port_line;
}
+ up->pins = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(up->pins)) {
+ dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
+ up->port.line, PTR_ERR(up->pins));
+ up->pins = NULL;
+ }
+
sprintf(up->name, "OMAP UART%d", up->port.line);
up->port.mapbase = mem->start;
up->port.membase = devm_ioremap(&pdev->dev, mem->start,
@@ -1509,20 +1403,6 @@ static int serial_omap_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "No clock speed specified: using default:"
"%d\n", DEFAULT_CLK_SPEED);
}
- up->uart_dma.uart_base = mem->start;
-
- if (omap_up_info->dma_enabled) {
- up->uart_dma.uart_dma_tx = dma_tx->start;
- up->uart_dma.uart_dma_rx = dma_rx->start;
- up->use_dma = 1;
- up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
- up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
- up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
- spin_lock_init(&(up->uart_dma.tx_lock));
- spin_lock_init(&(up->uart_dma.rx_lock));
- up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
- up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
- }
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
@@ -1531,12 +1411,13 @@ static int serial_omap_probe(struct platform_device *pdev)
serial_omap_uart_wq = create_singlethread_workqueue(up->name);
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
+ platform_set_drvdata(pdev, up);
+ pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(up);
@@ -1548,8 +1429,8 @@ static int serial_omap_probe(struct platform_device *pdev)
if (ret != 0)
goto err_add_port;
- pm_runtime_put(&pdev->dev);
- platform_set_drvdata(pdev, up);
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
return 0;
err_add_port:
@@ -1562,17 +1443,15 @@ err_port_line:
return ret;
}
-static int serial_omap_remove(struct platform_device *dev)
+static int __devexit serial_omap_remove(struct platform_device *dev)
{
struct uart_omap_port *up = platform_get_drvdata(dev);
- if (up) {
- pm_runtime_disable(&up->pdev->dev);
- uart_remove_one_port(&serial_omap_reg, &up->port);
- pm_qos_remove_request(&up->pm_qos_request);
- }
+ pm_runtime_put_sync(up->dev);
+ pm_runtime_disable(up->dev);
+ uart_remove_one_port(&serial_omap_reg, &up->port);
+ pm_qos_remove_request(&up->pm_qos_request);
- platform_set_drvdata(dev, NULL);
return 0;
}
@@ -1602,7 +1481,7 @@ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
timeout--;
if (!timeout) {
/* Should *never* happen. we warn and carry on */
- dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+ dev_crit(up->dev, "Errata i202: timedout %x\n",
serial_in(up, UART_LSR));
break;
}
@@ -1648,29 +1527,23 @@ static int serial_omap_runtime_suspend(struct device *dev)
if (!up)
return -EINVAL;
- if (!pdata || !pdata->enable_wakeup)
+ if (!pdata)
return 0;
- if (pdata->get_context_loss_count)
- up->context_loss_cnt = pdata->get_context_loss_count(dev);
+ up->context_loss_cnt = serial_omap_get_context_loss_count(up);
if (device_may_wakeup(dev)) {
if (!up->wakeups_enabled) {
- pdata->enable_wakeup(up->pdev, true);
+ serial_omap_enable_wakeup(up, true);
up->wakeups_enabled = true;
}
} else {
if (up->wakeups_enabled) {
- pdata->enable_wakeup(up->pdev, false);
+ serial_omap_enable_wakeup(up, false);
up->wakeups_enabled = false;
}
}
- /* Errata i291 */
- if (up->use_dma && pdata->set_forceidle &&
- (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
- pdata->set_forceidle(up->pdev);
-
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
schedule_work(&up->qos_work);
@@ -1683,17 +1556,10 @@ static int serial_omap_runtime_resume(struct device *dev)
struct omap_uart_port_info *pdata = dev->platform_data;
if (up && pdata) {
- if (pdata->get_context_loss_count) {
- u32 loss_cnt = pdata->get_context_loss_count(dev);
+ u32 loss_cnt = serial_omap_get_context_loss_count(up);
if (up->context_loss_cnt != loss_cnt)
serial_omap_restore_context(up);
- }
-
- /* Errata i291 */
- if (up->use_dma && pdata->set_noidle &&
- (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
- pdata->set_noidle(up->pdev);
up->latency = up->calc_latency;
schedule_work(&up->qos_work);
@@ -1721,7 +1587,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
- .remove = serial_omap_remove,
+ .remove = __devexit_p(serial_omap_remove),
.driver = {
.name = DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,