Linux Serial subsystem development
 help / color / mirror / Atom feed
* [PATCH v4 05/21] serial: omap: refactor receive_chars() into rdi/rlsi handlers
From: Felipe Balbi @ 2012-09-06 12:45 UTC (permalink / raw)
  To: Greg KH
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar, Felipe Balbi
In-Reply-To: <1346935540-1792-1-git-send-email-balbi@ti.com>

receive_chars() was getting too big and too difficult
to follow. By splitting it into separate RDI and RSLI
handlers, we have smaller functions which are easy
to understand and only touch the pieces which they need
to touch.

Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/tty/serial/omap-serial.c | 205 +++++++++++++++++++--------------------
 1 file changed, 101 insertions(+), 104 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d5a08cb..9c0a4ae 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -196,74 +196,6 @@ static void serial_omap_stop_rx(struct uart_port *port)
 	pm_runtime_put_autosuspend(up->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);
-}
-
 static void transmit_chars(struct uart_omap_port *up)
 {
 	struct circ_buf *xmit = &up->port.state->xmit;
@@ -342,6 +274,68 @@ 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
@@ -350,54 +344,57 @@ static unsigned int check_modem_status(struct uart_omap_port *up)
 static inline 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 int type;
 	unsigned long flags;
 	irqreturn_t ret = IRQ_NONE;
+	int max_count = 256;
 
 	spin_lock_irqsave(&up->port.lock, flags);
 	pm_runtime_get_sync(up->dev);
-	iir = serial_in(up, UART_IIR);
-again:
-	if (iir & UART_IIR_NO_INT)
-		goto out;
 
-	ret = IRQ_HANDLED;
-	lsr = serial_in(up, UART_LSR);
+	do {
+		iir = serial_in(up, UART_IIR);
+		if (iir & UART_IIR_NO_INT)
+			break;
 
-	/* extract IRQ type from IIR register */
-	type = iir & 0x3e;
+		ret = IRQ_HANDLED;
+		lsr = serial_in(up, UART_LSR);
 
-	switch (type) {
-	case UART_IIR_MSI:
-		check_modem_status(up);
-		break;
-	case UART_IIR_THRI:
-		if (lsr & UART_LSR_THRE)
-			transmit_chars(up);
-		break;
-	case UART_IIR_RDI:
-		if (lsr & UART_LSR_DR)
-			receive_chars(up, &lsr);
-		break;
-	case UART_IIR_RLSI:
-		if (lsr & UART_LSR_BRK_ERROR_BITS)
-			receive_chars(up, &lsr);
-		break;
-	case UART_IIR_RX_TIMEOUT:
-		receive_chars(up, &lsr);
-		break;
-	case UART_IIR_CTS_RTS_DSR:
-		iir = serial_in(up, UART_IIR);
-		goto again;
-	case UART_IIR_XOFF:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
+		/* extract IRQ type from IIR register */
+		type = iir & 0x3e;
+
+		switch (type) {
+		case UART_IIR_MSI:
+			check_modem_status(up);
+			break;
+		case UART_IIR_THRI:
+			if (lsr & UART_LSR_THRE)
+				transmit_chars(up);
+			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--);
 
-out:
 	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	tty_flip_buffer_push(tty);
+
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
 	up->port_activity = jiffies;
-- 
1.7.12.rc3

^ permalink raw reply related

* [PATCH v4 03/21] serial: add OMAP-specific defines
From: Felipe Balbi @ 2012-09-06 12:45 UTC (permalink / raw)
  To: Greg KH
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar, Felipe Balbi
In-Reply-To: <1346935540-1792-1-git-send-email-balbi@ti.com>

OMAP has some extra Interrupt types which can
be really useful for SW. Let's define them
so we can later use those in OMAP's serial driver.

Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 include/linux/serial_reg.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 8ce70d7..5ed325e 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -40,6 +40,10 @@
 
 #define UART_IIR_BUSY		0x07 /* DesignWare APB Busy Detect */
 
+#define UART_IIR_RX_TIMEOUT	0x0c /* OMAP RX Timeout interrupt */
+#define UART_IIR_XOFF		0x10 /* OMAP XOFF/Special Character */
+#define UART_IIR_CTS_RTS_DSR	0x20 /* OMAP CTS/RTS/DSR Change */
+
 #define UART_FCR	2	/* Out: FIFO Control Register */
 #define UART_FCR_ENABLE_FIFO	0x01 /* Enable the FIFO */
 #define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
-- 
1.7.12.rc3

^ permalink raw reply related

* [PATCH v4 02/21] serial: omap: drop DMA support
From: Felipe Balbi @ 2012-09-06 12:45 UTC (permalink / raw)
  To: Greg KH
  Cc: Kevin Hilman, Tony Lindgren, Linux Kernel Mailing List,
	Felipe Balbi, Santosh Shilimkar, linux-serial, Sourav Poddar,
	Linux OMAP Mailing List, Shubhrajyoti Datta,
	Linux ARM Kernel Mailing List, alan
In-Reply-To: <1346935540-1792-1-git-send-email-balbi@ti.com>

The current support is known to be broken and
a later patch will come re-adding it using
dma engine API.

Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 drivers/tty/serial/omap-serial.c | 330 ++-------------------------------------
 1 file changed, 12 insertions(+), 318 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 5af5d22..dd3971f 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -33,7 +33,6 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/io.h>
-#include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/serial_core.h>
 #include <linux/irq.h>
@@ -41,7 +40,6 @@
 #include <linux/of.h>
 #include <linux/gpio.h>
 
-#include <plat/dma.h>
 #include <plat/dmtimer.h>
 #include <plat/omap-serial.h>
 
@@ -75,9 +73,6 @@
 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;
@@ -161,19 +156,6 @@ 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->dev);
-		pm_runtime_put_autosuspend(up->dev);
-	}
-}
-
 static void serial_omap_enable_ms(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
@@ -189,22 +171,6 @@ static void serial_omap_enable_ms(struct uart_port *port)
 static void serial_omap_stop_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
-	struct omap_uart_port_info *pdata = up->dev->platform_data;
-
-	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->dev);
-		pm_runtime_put_autosuspend(up->dev);
-	}
 
 	pm_runtime_get_sync(up->dev);
 	if (up->ier & UART_IER_THRI) {
@@ -212,8 +178,7 @@ static void serial_omap_stop_tx(struct uart_port *port)
 		serial_out(up, UART_IER, up->ier);
 	}
 
-	if (!up->use_dma && pdata)
-		serial_omap_set_forceidle(up);
+	serial_omap_set_forceidle(up);
 
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
@@ -224,8 +189,6 @@ static void serial_omap_stop_rx(struct uart_port *port)
 	struct uart_omap_port *up = to_uart_omap_port(port);
 
 	pm_runtime_get_sync(up->dev);
-	if (up->use_dma)
-		serial_omap_stop_rxdma(up);
 	up->ier &= ~UART_IER_RLSI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
 	serial_out(up, UART_IER, up->ier);
@@ -343,67 +306,12 @@ 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 = to_uart_omap_port(port);
-	struct circ_buf *xmit;
-	unsigned int start;
-	int ret = 0;
-
-	if (!up->use_dma) {
-		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);
-		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->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));
 
-		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)
@@ -456,16 +364,8 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	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);
-		}
+		if (lsr & UART_LSR_DR)
+			receive_chars(up, &lsr);
 	}
 
 	check_modem_status(up);
@@ -616,20 +516,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
@@ -677,17 +563,6 @@ 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->dev);
 	free_irq(up->port.irq, up);
@@ -814,8 +689,6 @@ 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
@@ -891,14 +764,9 @@ 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 1 byte */
+	up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
+	up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);
 
 	serial_out(up, UART_FCR, up->fcr);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -1267,149 +1135,6 @@ 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->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 = 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)
 {
 	u32 mvr, scheme;
@@ -1479,7 +1204,7 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
 static int 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;
 
@@ -1504,14 +1229,6 @@ 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");
@@ -1574,20 +1291,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;
@@ -1730,10 +1433,6 @@ static int serial_omap_runtime_suspend(struct device *dev)
 		}
 	}
 
-	/* Errata i291 */
-	if (up->use_dma && (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
-		serial_omap_set_forceidle(up);
-
 	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
 	schedule_work(&up->qos_work);
 
@@ -1751,11 +1450,6 @@ static int serial_omap_runtime_resume(struct device *dev)
 			if (up->context_loss_cnt != loss_cnt)
 				serial_omap_restore_context(up);
 
-		/* Errata i291 */
-		if ((up->errata & UART_ERRATA_i291_DMA_FORCEIDLE) &&
-				up->use_dma)
-			serial_omap_set_noidle(up);
-
 		up->latency = up->calc_latency;
 		schedule_work(&up->qos_work);
 	}
-- 
1.7.12.rc3

^ permalink raw reply related

* [PATCH v4 01/21] serial: omap: don't access the platform_device
From: Felipe Balbi @ 2012-09-06 12:45 UTC (permalink / raw)
  To: Greg KH
  Cc: Kevin Hilman, Tony Lindgren, Linux Kernel Mailing List,
	Felipe Balbi, Santosh Shilimkar, linux-serial, Sourav Poddar,
	Linux OMAP Mailing List, Shubhrajyoti Datta,
	Linux ARM Kernel Mailing List, alan
In-Reply-To: <1346935540-1792-1-git-send-email-balbi@ti.com>

The driver doesn't need to know about its platform_device.

Everything the driver needs can be done through the
struct device pointer. In case we need to use the
OMAP-specific PM function pointers, those can make
sure to find the device's platform_device pointer
so they can find the struct omap_device through
pdev->archdata field.

Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
---
 arch/arm/mach-omap2/serial.c                  |  15 ++--
 arch/arm/plat-omap/include/plat/omap-serial.h |  10 +--
 drivers/tty/serial/omap-serial.c              | 124 +++++++++++++-------------
 3 files changed, 76 insertions(+), 73 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 25d53b2..9e80d20 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -81,8 +81,9 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
 };
 
 #ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	if (!od)
@@ -99,15 +100,17 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
  * in Smartidle Mode When Configured for DMA Operations.
  * WA: configure uart in force idle mode.
  */
-static void omap_uart_set_noidle(struct platform_device *pdev)
+static void omap_uart_set_noidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
 }
 
-static void omap_uart_set_smartidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 	u8 idlemode;
 
@@ -120,10 +123,10 @@ static void omap_uart_set_smartidle(struct platform_device *pdev)
 }
 
 #else
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {}
-static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_smartidle(struct platform_device *pdev) {}
+static void omap_uart_set_noidle(struct device *dev) {}
+static void omap_uart_set_smartidle(struct device *dev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 5cc0626..90d2d74 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -18,7 +18,7 @@
 #define __OMAP_SERIAL_H__
 
 #include <linux/serial_core.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
 #include <linux/pm_qos.h>
 
 #include <plat/mux.h>
@@ -74,9 +74,9 @@ struct omap_uart_port_info {
 	int			DTR_present;
 
 	int (*get_context_loss_count)(struct device *);
-	void (*set_forceidle)(struct platform_device *);
-	void (*set_noidle)(struct platform_device *);
-	void (*enable_wakeup)(struct platform_device *, bool);
+	void (*set_forceidle)(struct device *);
+	void (*set_noidle)(struct device *);
+	void (*enable_wakeup)(struct device *, bool);
 };
 
 struct uart_omap_dma {
@@ -108,7 +108,7 @@ struct uart_omap_dma {
 struct uart_omap_port {
 	struct uart_port	port;
 	struct uart_omap_dma	uart_dma;
-	struct platform_device	*pdev;
+	struct device		*dev;
 
 	unsigned char		ier;
 	unsigned char		lcr;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 3a60b86..5af5d22 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -104,36 +104,36 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
 
 static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
 {
-	struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
+	struct omap_uart_port_info *pdata = up->dev->platform_data;
 
 	if (!pdata->get_context_loss_count)
 		return 0;
 
-	return pdata->get_context_loss_count(&up->pdev->dev);
+	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->pdev->dev.platform_data;
+	struct omap_uart_port_info *pdata = up->dev->platform_data;
 
 	if (pdata->set_forceidle)
-		pdata->set_forceidle(up->pdev);
+		pdata->set_forceidle(up->dev);
 }
 
 static void serial_omap_set_noidle(struct uart_omap_port *up)
 {
-	struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
+	struct omap_uart_port_info *pdata = up->dev->platform_data;
 
 	if (pdata->set_noidle)
-		pdata->set_noidle(up->pdev);
+		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->pdev->dev.platform_data;
+	struct omap_uart_port_info *pdata = up->dev->platform_data;
 
 	if (pdata->enable_wakeup)
-		pdata->enable_wakeup(up->pdev, enable);
+		pdata->enable_wakeup(up->dev, enable);
 }
 
 /*
@@ -169,8 +169,8 @@ static void serial_omap_stop_rxdma(struct uart_omap_port *up)
 		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);
+		pm_runtime_mark_last_busy(up->dev);
+		pm_runtime_put_autosuspend(up->dev);
 	}
 }
 
@@ -180,16 +180,16 @@ static void serial_omap_enable_ms(struct uart_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_put(up->dev);
 }
 
 static void serial_omap_stop_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
-	struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;
+	struct omap_uart_port_info *pdata = up->dev->platform_data;
 
 	if (up->use_dma &&
 		up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
@@ -202,11 +202,11 @@ static void serial_omap_stop_tx(struct uart_port *port)
 		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_mark_last_busy(up->dev);
+		pm_runtime_put_autosuspend(up->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);
@@ -215,22 +215,22 @@ static void serial_omap_stop_tx(struct uart_port *port)
 	if (!up->use_dma && pdata)
 		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 = to_uart_omap_port(port);
 
-	pm_runtime_get_sync(&up->pdev->dev);
+	pm_runtime_get_sync(up->dev);
 	if (up->use_dma)
 		serial_omap_stop_rxdma(up);
 	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);
+	pm_runtime_mark_last_busy(up->dev);
+	pm_runtime_put_autosuspend(up->dev);
 }
 
 static inline void receive_chars(struct uart_omap_port *up,
@@ -348,11 +348,11 @@ static void serial_omap_start_tx(struct uart_port *port)
 	int ret = 0;
 
 	if (!up->use_dma) {
-		pm_runtime_get_sync(&up->pdev->dev);
+		pm_runtime_get_sync(up->dev);
 		serial_omap_enable_ier_thri(up);
 		serial_omap_set_noidle(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);
 		return;
 	}
 
@@ -362,7 +362,7 @@ static void serial_omap_start_tx(struct uart_port *port)
 	xmit = &up->port.state->xmit;
 
 	if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
-		pm_runtime_get_sync(&up->pdev->dev);
+		pm_runtime_get_sync(up->dev);
 		ret = omap_request_dma(up->uart_dma.uart_dma_tx,
 				"UART Tx DMA",
 				(void *)uart_tx_dma_callback, up,
@@ -445,11 +445,11 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
 	unsigned int iir, lsr;
 	unsigned long flags;
 
-	pm_runtime_get_sync(&up->pdev->dev);
+	pm_runtime_get_sync(up->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);
+		pm_runtime_mark_last_busy(up->dev);
+		pm_runtime_put_autosuspend(up->dev);
 		return IRQ_NONE;
 	}
 
@@ -473,8 +473,8 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
 		transmit_chars(up);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
-	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 IRQ_HANDLED;
@@ -486,12 +486,12 @@ static unsigned int serial_omap_tx_empty(struct uart_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_put(up->dev);
 	return ret;
 }
 
@@ -501,9 +501,9 @@ static unsigned int serial_omap_get_mctrl(struct uart_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_put(up->dev);
 
 	dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
 
@@ -535,11 +535,11 @@ 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_put(up->dev);
 
 	if (gpio_is_valid(up->DTR_gpio) &&
 	    !!(mctrl & TIOCM_DTR) != up->DTR_active) {
@@ -558,7 +558,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
 	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;
@@ -566,7 +566,7 @@ 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_put(up->dev);
 }
 
 static int serial_omap_startup(struct uart_port *port)
@@ -585,7 +585,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())
@@ -641,8 +641,8 @@ 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;
 }
@@ -654,7 +654,7 @@ static void serial_omap_shutdown(struct uart_port *port)
 
 	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
 	 */
@@ -689,7 +689,7 @@ static void serial_omap_shutdown(struct uart_port *port)
 		up->uart_dma.rx_buf = NULL;
 	}
 
-	pm_runtime_put(&up->pdev->dev);
+	pm_runtime_put(up->dev);
 	free_irq(up->port.irq, up);
 }
 
@@ -821,7 +821,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * 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);
 
 	/*
@@ -970,7 +970,7 @@ 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_put(up->dev);
 	dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
 }
 
@@ -983,7 +983,7 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
 
 	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);
@@ -994,14 +994,14 @@ 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_put(up->dev);
 }
 
 static void serial_omap_release_port(struct uart_port *port)
@@ -1080,10 +1080,10 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
 {
 	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_put(up->dev);
 }
 
 static int serial_omap_poll_get_char(struct uart_port *port)
@@ -1091,13 +1091,13 @@ static int serial_omap_poll_get_char(struct uart_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;
 
 	status = serial_in(up, UART_RX);
-	pm_runtime_put(&up->pdev->dev);
+	pm_runtime_put(up->dev);
 	return status;
 }
 
@@ -1126,7 +1126,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)
@@ -1160,8 +1160,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);
@@ -1323,7 +1323,7 @@ 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);
+		pm_runtime_get_sync(up->dev);
 		ret = omap_request_dma(up->uart_dma.uart_dma_rx,
 				"UART Rx DMA",
 				(void *)uart_rx_dma_callback, up,
@@ -1435,7 +1435,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 */
@@ -1535,7 +1535,7 @@ static int serial_omap_probe(struct platform_device *pdev)
 		up->DTR_gpio = -EINVAL;
 	up->DTR_active = 0;
 
-	up->pdev = pdev;
+	up->dev = &pdev->dev;
 	up->port.dev = &pdev->dev;
 	up->port.type = PORT_OMAP;
 	up->port.iotype = UPIO_MEM;
@@ -1632,7 +1632,7 @@ static int serial_omap_remove(struct platform_device *dev)
 	struct uart_omap_port *up = platform_get_drvdata(dev);
 
 	if (up) {
-		pm_runtime_disable(&up->pdev->dev);
+		pm_runtime_disable(up->dev);
 		uart_remove_one_port(&serial_omap_reg, &up->port);
 		pm_qos_remove_request(&up->pm_qos_request);
 	}
@@ -1667,7 +1667,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;
 		}
-- 
1.7.12.rc3

^ permalink raw reply related

* [PATCH v4 00/21] OMAP UART Patches
From: Felipe Balbi @ 2012-09-06 12:45 UTC (permalink / raw)
  To: Greg KH
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar, Felipe Balbi
In-Reply-To: <20120906122948.GC29202@arwen.pp.htv.fi>

Hi guys,

here's v4 of the omap uart patchset. No changes other than a rebase on top of
Greg's tty-next branch and Tony's Acked-by being added to a couple patches

Note: I'm resending the series with Vikram's Software Flow Control fix anyway
as it can just be ignored if it's decided it needs to go into this merge
window.

Changes since v3:
	. Rebased on top of Greg's tty-next branch
	. Added Tony's Acked-by

Changes since v2:
        . Added a bunch of new patches
        . Fixed a problem where we would always return IRQ_NONE even though we
                handled IRQ

Changes since v1:
        . improved commit log on patch 9/13 (formerly 10/13)
        . removed patch 2/13
        . added a new patch switching from spin_lock_irqsave() to spin_lock and
                spin_unlock_irqrestore to spin_unlock

Felipe Balbi (18):
  serial: omap: don't access the platform_device
  serial: omap: drop DMA support
  serial: add OMAP-specific defines
  serial: omap: simplify IRQ handling
  serial: omap: refactor receive_chars() into rdi/rlsi handlers
  serial: omap: move THRE check to transmit_chars()
  serial: omap: stick to put_autosuspend
  serial: omap: set dev->drvdata before enabling pm_runtime
  serial: omap: drop unnecessary check from remove
  serial: omap: make sure to suspend device before remove
  serial: omap: don't save IRQ flags on hardirq
  serial: omap: optimization with section annotations
  serial: omap: drop "inline" from IRQ handler prototype
  serial: omap: implement set_wake
  serial: omap: make sure to put() on poll_get_char
  serial: omap: remove unnecessary header and add a missing one
  serial: omap: move uart_omap_port definition to C file
  serial: omap: enable RX and TX FIFO usage

Ruchika Kharwar (2):
  serial: omap: fix sequence of pm_runtime_* calls.
  serial: omap: unlock the port lock

Vikram Pandita (1):
  serial: omap: fix software flow control

 arch/arm/mach-omap2/serial.c                  |  15 +-
 arch/arm/plat-omap/include/plat/omap-serial.h |  49 +-
 drivers/tty/serial/omap-serial.c              | 740 +++++++++-----------------
 include/linux/serial_reg.h                    |   4 +
 4 files changed, 282 insertions(+), 526 deletions(-)

-- 
1.7.12.rc3

^ permalink raw reply

* Re: [PATCH v3 20/23] serial: omap: fix software flow control
From: Felipe Balbi @ 2012-09-06 12:31 UTC (permalink / raw)
  To: Greg KH
  Cc: Felipe Balbi, alan, Tony Lindgren, Kevin Hilman,
	Linux OMAP Mailing List, Linux ARM Kernel Mailing List,
	linux-serial, Linux Kernel Mailing List, Santosh Shilimkar,
	Shubhrajyoti Datta, Sourav Poddar, Vikram Pandita, stable
In-Reply-To: <20120905202749.GA2451@kroah.com>

[-- Attachment #1: Type: text/plain, Size: 983 bytes --]

On Wed, Sep 05, 2012 at 01:27:49PM -0700, Greg KH wrote:
> On Thu, Aug 23, 2012 at 01:33:00PM +0300, Felipe Balbi wrote:
> > From: Vikram Pandita <vikram.pandita@ti.com>
> > 
> > Software flow control register bits were not defined correctly.
> > 
> > Also clarify the IXON and IXOFF logic to reflect what userspace wants.
> > 
> > Cc: stable@vger.kernel.org
> > Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> > Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
> > Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> > Signed-off-by: Felipe Balbi <balbi@ti.com>
> > Acked-by: Tony Lindgren <tony@atomide.com>
> > ---
> 
> If this is a stable patch, should it be pulled out and put also in for
> 3.6?

I'll leave that for Vikram to answer. Vikram, do you think this is
something so extreme that we _must_ apply it now, or can it wait for the
next merge window ?

I mean, I think this bug has been in the driver for a long time, right ?

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v3 03/23] serial: omap: don't access the platform_device
From: Felipe Balbi @ 2012-09-06 12:29 UTC (permalink / raw)
  To: Greg KH
  Cc: Felipe Balbi, alan, Tony Lindgren, Kevin Hilman,
	Linux OMAP Mailing List, Linux ARM Kernel Mailing List,
	linux-serial, Linux Kernel Mailing List, Santosh Shilimkar,
	Shubhrajyoti Datta, Sourav Poddar
In-Reply-To: <20120905202721.GA2430@kroah.com>

[-- Attachment #1: Type: text/plain, Size: 1002 bytes --]

On Wed, Sep 05, 2012 at 01:27:21PM -0700, Greg KH wrote:
> On Thu, Aug 23, 2012 at 01:32:43PM +0300, Felipe Balbi wrote:
> > The driver doesn't need to know about its platform_device.
> > 
> > Everything the driver needs can be done through the
> > struct device pointer. In case we need to use the
> > OMAP-specific PM function pointers, those can make
> > sure to find the device's platform_device pointer
> > so they can find the struct omap_device through
> > pdev->archdata field.
> > 
> > Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> > Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Signed-off-by: Felipe Balbi <balbi@ti.com>
> > Acked-by: Tony Lindgren <tony@atomide.com>
> 
> This series fails when applying to my tty-next branch at this patch :(
> 
> Care to refresh it, and resend it, with Tony's acks added, so I can
> apply it?  Note, I've already applied the first two.

Sure, will do and reply to this mail with the new series. Thanks

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] serial_core: fix sizeof(pointer)
From: Alan Cox @ 2012-09-06 11:48 UTC (permalink / raw)
  To: Fengguang Wu; +Cc: linux-serial, Jiri Slaby, Greg Kroah-Hartman, LKML
In-Reply-To: <20120906022751.GA16285@localhost>

On Thu, 6 Sep 2012 10:27:51 +0800
Fengguang Wu <fengguang.wu@intel.com> wrote:

> sizeof when applied to a pointer typed expression gives the
> size of the pointer.
> 
> Generated by: scripts/coccinelle/misc/noderef.cocci
> 
> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>


Oops.. yes typo on my part

Signed-off-by: Alan Cox <alan@linux.intel.com>

^ permalink raw reply

* Re: [PATCH] serial_core: fix sizeof(pointer)
From: Fengguang Wu @ 2012-09-06  7:08 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-serial, Alan Cox, Greg Kroah-Hartman, LKML
In-Reply-To: <504849B4.4050303@suse.cz>

On Thu, Sep 06, 2012 at 08:59:00AM +0200, Jiri Slaby wrote:
> On 09/06/2012 04:27 AM, Fengguang Wu wrote:
> > sizeof when applied to a pointer typed expression gives the
> > size of the pointer.
> > 
> > Generated by: scripts/coccinelle/misc/noderef.cocci
> > 
> > Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
> > ---
> > 
> >  cocci-output-38612-39d907-serial_core.c |    2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > --- a/drivers/tty/serial/serial_core.c
> > +++ b/drivers/tty/serial/serial_core.c
> > @@ -640,7 +640,7 @@ static void uart_get_info(struct tty_por
> >  {
> >  	struct uart_port *uport = state->uart_port;
> >  
> > -	memset(retinfo, 0, sizeof(retinfo));
> > +	memset(retinfo, 0, sizeof(*retinfo));
> 
> Hmm, what tree is this against? I have:

It's the tty:tty-next tree.

        git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-next

> memset(&tmp, 0, sizeof(tmp));

Oh I didn't know it's a new bug introduced by commit

        commit 7ba2e769825fef035a943ed74d90379245508764
        Author:     Alan Cox <alan@linux.intel.com>
        AuthorDate: Tue Sep 4 16:34:45 2012 +0100
        Commit:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        CommitDate: Wed Sep 5 13:11:03 2012 -0700

            tty: Split the serial_core helpers for setserial into two

Thanks,
Fengguang

^ permalink raw reply

* Re: [PATCH] serial_core: fix sizeof(pointer)
From: Jiri Slaby @ 2012-09-06  6:59 UTC (permalink / raw)
  To: Fengguang Wu; +Cc: linux-serial, Alan Cox, Greg Kroah-Hartman, LKML
In-Reply-To: <20120906022751.GA16285@localhost>

On 09/06/2012 04:27 AM, Fengguang Wu wrote:
> sizeof when applied to a pointer typed expression gives the
> size of the pointer.
> 
> Generated by: scripts/coccinelle/misc/noderef.cocci
> 
> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
> ---
> 
>  cocci-output-38612-39d907-serial_core.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -640,7 +640,7 @@ static void uart_get_info(struct tty_por
>  {
>  	struct uart_port *uport = state->uart_port;
>  
> -	memset(retinfo, 0, sizeof(retinfo));
> +	memset(retinfo, 0, sizeof(*retinfo));

Hmm, what tree is this against? I have:

memset(&tmp, 0, sizeof(tmp));

thanks,
-- 
js
suse labs

^ permalink raw reply

* Re: [PATCH] Add PCI IDs and quirks for WCH CH353 2S1P card
From: gianluca @ 2012-09-06  6:41 UTC (permalink / raw)
  To: Greg KH; +Cc: Alan Cox, linux-serial
In-Reply-To: <20120905233804.GA12305@kroah.com>

On Wed, Sep 05, 2012 at 04:38:04PM -0700, Greg KH wrote:
> This patch doesn't apply at all to the tty-next branch of the linux-next
> tree, which is where I need to apply it.  Can you redo it against that
> branch and resend it so that I can apply it properly?
> 
> thanks,
> 
> greg k-h

no need for that, as it has been already submitted by Alan Cox and accepted in
your tty-next tree as commit 6971c635af27b1d18d409e337e70bae25d2fa8ec
parport_serial: Add support for the WCH353 2S/1P multi-IO card

I see my name in the Author field was mispelled, but the patch is ok :)

Thank you

Gianluca

^ permalink raw reply

* [PATCH] serial_core: fix sizeof(pointer)
From: Fengguang Wu @ 2012-09-06  2:27 UTC (permalink / raw)
  To: linux-serial; +Cc: Alan Cox, Jiri Slaby, Greg Kroah-Hartman, LKML

sizeof when applied to a pointer typed expression gives the
size of the pointer.

Generated by: scripts/coccinelle/misc/noderef.cocci

Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
---

 cocci-output-38612-39d907-serial_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -640,7 +640,7 @@ static void uart_get_info(struct tty_por
 {
 	struct uart_port *uport = state->uart_port;
 
-	memset(retinfo, 0, sizeof(retinfo));
+	memset(retinfo, 0, sizeof(*retinfo));
 
 	retinfo->type	    = uport->type;
 	retinfo->line	    = uport->line;

^ permalink raw reply

* [PATCH v6] uartclk value from serial_core exposed to sysfs
From: Tomas Hlavacek @ 2012-09-06  1:17 UTC (permalink / raw)
  To: gregkh, alan, linux-serial, linux-kernel; +Cc: marek.vasut, Tomas Hlavacek
In-Reply-To: <1344929718-22736-1-git-send-email-tmshlvck@gmail.com>

Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

tty_register_device() has been generalized and refactored in order
to add support for setting drvdata and attribute_group to the device.

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 Documentation/ABI/testing/sysfs-tty |    9 +++++
 drivers/tty/serial/serial_core.c    |   34 ++++++++++++++++-
 drivers/tty/tty_io.c                |   69 ++++++++++++++++++++++++++++++-----
 include/linux/tty.h                 |    4 ++
 4 files changed, 104 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index b138b66..0c43015 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -17,3 +17,12 @@ Description:
 		 device, like 'tty1'.
 		 The file supports poll() to detect virtual
 		 console switches.
+
+What:		/sys/class/tty/ttyS0/uartclk
+Date:		Sep 2012
+Contact:	Tomas Hlavacek <tmshlvck@gmail.com>
+Description:
+		 Shows the current uartclk value associated with the
+		 UART port in serial_core, that is bound to TTY like ttyS0.
+		 uartclk = 16 * baud_base
+
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 137b25c..5d212f8 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2309,6 +2309,36 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
 	return p->tty_driver;
 }
 
+static ssize_t uart_get_attr_uartclk(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	int ret;
+
+	struct tty_port *port = dev_get_drvdata(dev);
+	struct uart_state *state = container_of(port, struct uart_state, port);
+	mutex_lock(&state->port.mutex);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+	mutex_unlock(&state->port.mutex);
+
+	return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+	&dev_attr_uartclk.attr,
+	NULL,
+	};
+
+static struct attribute_group tty_dev_attr_group = {
+	.attrs = tty_dev_attrs,
+	};
+
+static const struct attribute_group *tty_dev_attr_groups[] = {
+	&tty_dev_attr_group,
+	NULL
+	};
+
 /**
  *	uart_add_one_port - attach a driver-defined port structure
  *	@drv: pointer to the uart low level driver structure for this port
@@ -2362,8 +2392,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this ports parameters.
 	 */
-	tty_dev = tty_port_register_device(port, drv->tty_driver, uport->line,
-			uport->dev);
+	tty_dev = tty_register_device_attr(drv->tty_driver, uport->line,
+			uport->dev, port, tty_dev_attr_groups);
 	if (likely(!IS_ERR(tty_dev))) {
 		device_set_wakeup_capable(tty_dev, 1);
 	} else {
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index d3bf91a..dcb30d5 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3041,9 +3041,39 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
 struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 				   struct device *device)
 {
-	struct device *ret;
+	return tty_register_device_attr(driver, index, device, NULL, NULL);
+}
+EXPORT_SYMBOL(tty_register_device);
+
+/**
+ *	tty_register_device_attr - register a tty device
+ *	@driver: the tty driver that describes the tty device
+ *	@index: the index in the tty driver for this tty device
+ *	@device: a struct device that is associated with this tty device.
+ *		This field is optional, if there is no known struct device
+ *		for this tty device it can be set to NULL safely.
+ *	@drvdata: Driver data to be set to device.
+ *	@attr_grp: Attribute group to be set on device.
+ *
+ *	Returns a pointer to the struct device for this tty device
+ *	(or ERR_PTR(-EFOO) on error).
+ *
+ *	This call is required to be made to register an individual tty device
+ *	if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set.  If
+ *	that bit is not set, this function should not be called by a tty
+ *	driver.
+ *
+ *	Locking: ??
+ */
+struct device *tty_register_device_attr(struct tty_driver *driver,
+				   unsigned index, struct device *device,
+				   void *drvdata,
+				   const struct attribute_group **attr_grp)
+{
 	char name[64];
-	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
+	dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
+	struct device *dev = NULL;
+	int retval = -ENODEV;
 	bool cdev = false;
 
 	if (index >= driver->num) {
@@ -3058,19 +3088,38 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 		tty_line_name(driver, index, name);
 
 	if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
-		int error = tty_cdev_add(driver, dev, index, 1);
-		if (error)
-			return ERR_PTR(error);
+		retval = tty_cdev_add(driver, devt, index, 1);
+		if (retval)
+			goto error;
 		cdev = true;
 	}
 
-	ret = device_create(tty_class, device, dev, NULL, name);
-	if (IS_ERR(ret) && cdev)
-		cdev_del(&driver->cdevs[index]);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		retval = -ENOMEM;
+		goto error;
+	}
 
-	return ret;
+	dev->devt = devt;
+	dev->class = tty_class;
+	dev->parent = device;
+	dev_set_name(dev, "%s", name);
+	dev->groups = attr_grp;
+	dev_set_drvdata(dev, drvdata);
+
+	retval = device_register(dev);
+	if (retval)
+		goto error;
+
+	return dev;
+
+error:
+	put_device(dev);
+	if (cdev)
+		cdev_del(&driver->cdevs[index]);
+	return ERR_PTR(retval);
 }
-EXPORT_SYMBOL(tty_register_device);
+EXPORT_SYMBOL_GPL(tty_register_device_attr);
 
 /**
  * 	tty_unregister_device - unregister a tty device
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9892121..599d603 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -412,6 +412,10 @@ extern int tty_register_driver(struct tty_driver *driver);
 extern int tty_unregister_driver(struct tty_driver *driver);
 extern struct device *tty_register_device(struct tty_driver *driver,
 					  unsigned index, struct device *dev);
+extern struct device *tty_register_device_attr(struct tty_driver *driver,
+				unsigned index, struct device *device,
+				void *drvdata,
+				const struct attribute_group **attr_grp);
 extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 			     int buflen);
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCHv5 1/1] uartclk value from serial_core exposed to sysfs
From: Tomas Hlavacek @ 2012-09-06  1:01 UTC (permalink / raw)
  To: Greg KH; +Cc: alan, linux-serial, linux-kernel, marek.vasut
In-Reply-To: <20120905234220.GA30393@kroah.com>

Hello Greg,

On Thu, Sep 6, 2012 at 1:42 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Thu, Sep 06, 2012 at 01:16:56AM +0200, Tomas Hlavacek wrote:
>> Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
>> uartclk value in struct uart_port in serial_core via sysfs.
>>
>> tty_register_device() has been generalized and refactored in order
>> to add support for setting drvdata and attribute_group to the device.
>>
>> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
>> ---
>>  Documentation/ABI/testing/sysfs-tty |    9 ++++++
>>  drivers/tty/serial/serial_core.c    |   36 ++++++++++++++++++++-
>>  drivers/tty/tty_io.c                |   59 +++++++++++++++++++++++++++++++++--
>>  include/linux/tty.h                 |    4 +++
>>  4 files changed, 104 insertions(+), 4 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
>> index b138b66..2f10855 100644
>
> Odd, what tree did you make this against?  It doesn't apply at all, even
> if I mess with it to try a --3way merge, it still throws up a ton of
> conflicts.
>
> Care to do it against my tty-next branch in git?

I did it wrong obviously. Sorry. I am resending it (it is going to be
against tty-next branch in
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git, I hope
it is right this time).

Tomas

^ permalink raw reply

* Re: [PATCHv5 1/1] uartclk value from serial_core exposed to sysfs
From: Greg KH @ 2012-09-05 23:42 UTC (permalink / raw)
  To: Tomas Hlavacek; +Cc: alan, linux-serial, linux-kernel, marek.vasut
In-Reply-To: <1346887016-10415-1-git-send-email-tmshlvck@gmail.com>

On Thu, Sep 06, 2012 at 01:16:56AM +0200, Tomas Hlavacek wrote:
> Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
> uartclk value in struct uart_port in serial_core via sysfs.
> 
> tty_register_device() has been generalized and refactored in order
> to add support for setting drvdata and attribute_group to the device.
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
> ---
>  Documentation/ABI/testing/sysfs-tty |    9 ++++++
>  drivers/tty/serial/serial_core.c    |   36 ++++++++++++++++++++-
>  drivers/tty/tty_io.c                |   59 +++++++++++++++++++++++++++++++++--
>  include/linux/tty.h                 |    4 +++
>  4 files changed, 104 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
> index b138b66..2f10855 100644

Odd, what tree did you make this against?  It doesn't apply at all, even
if I mess with it to try a --3way merge, it still throws up a ton of
conflicts.

Care to do it against my tty-next branch in git?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] Add PCI IDs and quirks for WCH CH353 2S1P card
From: Greg KH @ 2012-09-05 23:38 UTC (permalink / raw)
  To: gianluca; +Cc: Alan Cox, linux-serial
In-Reply-To: <20120829182429.GA15239@server>

On Wed, Aug 29, 2012 at 08:24:29PM +0200, gianluca wrote:
> Add new PCI ids for WCH CH353 2Serial 1Parallel Multi-IO PCI Card to
> parport_serial.c.
> 
> To allow parport_serial to handle the card the same PCI ids are blacklisted
> in 8250_pci.c using the existing softmodem blacklist mechanism.
> 
> The blacklist array is also renamed because it now covers this new use case.
> 
> Since the two serial ports are autodetected as XScale instead of 16550A clones,
> add also a quirk to 8250_pci.c to skip autodetection and set the correct port
> type.
> 
> The patch is against linux v3.5.3 but applies cleanly also to latest git head.

This patch doesn't apply at all to the tty-next branch of the linux-next
tree, which is where I need to apply it.  Can you redo it against that
branch and resend it so that I can apply it properly?

thanks,

greg k-h

^ permalink raw reply

* [PATCHv5 1/1] uartclk value from serial_core exposed to sysfs
From: Tomas Hlavacek @ 2012-09-05 23:16 UTC (permalink / raw)
  To: gregkh, alan, linux-serial, linux-kernel; +Cc: marek.vasut, Tomas Hlavacek
In-Reply-To: <1344929718-22736-1-git-send-email-tmshlvck@gmail.com>

Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
uartclk value in struct uart_port in serial_core via sysfs.

tty_register_device() has been generalized and refactored in order
to add support for setting drvdata and attribute_group to the device.

Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>
---
 Documentation/ABI/testing/sysfs-tty |    9 ++++++
 drivers/tty/serial/serial_core.c    |   36 ++++++++++++++++++++-
 drivers/tty/tty_io.c                |   59 +++++++++++++++++++++++++++++++++--
 include/linux/tty.h                 |    4 +++
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index b138b66..2f10855 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -17,3 +17,12 @@ Description:
 		 device, like 'tty1'.
 		 The file supports poll() to detect virtual
 		 console switches.
+
+What:		/sys/class/tty/ttyS0/uartclk
+Date:		Sep 2012
+Contact:	Tomas Hlavacek <tmshlvck@gmail.com>
+Description:
+		Shows the current uartclk value associated with the
+		UART port in serial_core, that is bound to TTY like ttyS0.
+		uartclk = 16 * baud_base
+
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index a21dc8e..ca64a93 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2293,6 +2293,37 @@ struct tty_driver *uart_console_device(struct console *co, int *index)
 	return p->tty_driver;
 }
 
+static ssize_t uart_get_attr_uartclk(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+int ret;
+
+struct tty_port *port = dev_get_drvdata(dev);
+struct uart_state *state = container_of(port, struct uart_state, port);
+mutex_lock(&state->port.mutex);
+ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk);
+mutex_unlock(&state->port.mutex);
+
+return ret;
+}
+
+static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk,
+	NULL);
+
+static struct attribute *tty_dev_attrs[] = {
+	&dev_attr_uartclk.attr,
+	NULL,
+	};
+
+static struct attribute_group tty_dev_attr_group = {
+	.attrs = tty_dev_attrs,
+};
+
+static const struct attribute_group *tty_dev_attr_groups[] = {
+	&tty_dev_attr_group,
+	NULL
+	};
+
 /**
  *	uart_add_one_port - attach a driver-defined port structure
  *	@drv: pointer to the uart low level driver structure for this port
@@ -2345,8 +2376,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 	/*
 	 * Register the port whether it's detected or not.  This allows
 	 * setserial to be used to alter this ports parameters.
+	 * Use driverdata of the tty device for referencing the UART port.
+	 * Set default device attributes to the new device.
 	 */
-	tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
+	tty_dev = tty_register_device_attr(drv->tty_driver, uport->line,
+			uport->dev, port, tty_dev_attr_groups);
 	if (likely(!IS_ERR(tty_dev))) {
 		device_set_wakeup_capable(tty_dev, 1);
 	} else {
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index b425c79..befa99c 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3013,8 +3013,39 @@ struct class *tty_class;
 struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 				   struct device *device)
 {
+	return tty_register_device_attr(driver, index, device, NULL, NULL);
+}
+EXPORT_SYMBOL(tty_register_device);
+
+/**
+ *	tty_register_device_attr - register a tty device
+ *	@driver: the tty driver that describes the tty device
+ *	@index: the index in the tty driver for this tty device
+ *	@device: a struct device that is associated with this tty device.
+ *		 This field is optional, if there is no known struct device
+ *		 for this tty device it can be set to NULL safely.
+ *	@drvdata: Driver data to be set to device.
+ *	@attr_grp: Attribute group to be set on device.
+ *
+ *	Returns a pointer to the struct device for this tty device
+ *	(or ERR_PTR(-EFOO) on error).
+ *
+ *	This call is required to be made to register an individual tty device
+ *	if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set.  If
+ *	that bit is not set, this function should not be called by a tty
+ *	driver.
+ *
+ *	Locking: ??
+ */
+struct device *tty_register_device_attr(struct tty_driver *driver,
+				   unsigned index, struct device *device,
+				   void *drvdata,
+				   const struct attribute_group **attr_grp)
+{
 	char name[64];
-	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
+	struct device *dev = NULL;
+	int retval = -ENODEV;
+	dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
 
 	if (index >= driver->num) {
 		printk(KERN_ERR "Attempt to register invalid tty line number "
@@ -3027,9 +3058,31 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
 	else
 		tty_line_name(driver, index, name);
 
-	return device_create(tty_class, device, dev, NULL, name);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	dev->devt = devt;
+	dev->class = tty_class;
+	dev->parent = device;
+	dev_set_name(dev, "%s", name);
+	dev->groups = attr_grp;
+	dev_set_drvdata(dev, drvdata);
+
+	retval = device_register(dev);
+	if (retval)
+		goto error;
+
+	return dev;
+
+error:
+	put_device(dev);
+	return ERR_PTR(retval);
 }
-EXPORT_SYMBOL(tty_register_device);
+EXPORT_SYMBOL_GPL(tty_register_device_attr);
 
 /**
  * 	tty_unregister_device - unregister a tty device
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 9f47ab5..664252b 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -410,6 +410,10 @@ extern int tty_register_driver(struct tty_driver *driver);
 extern int tty_unregister_driver(struct tty_driver *driver);
 extern struct device *tty_register_device(struct tty_driver *driver,
 					  unsigned index, struct device *dev);
+extern struct device *tty_register_device_attr(struct tty_driver *driver,
+				unsigned index, struct device *device,
+				void *drvdata,
+				const struct attribute_group **attr_grp);
 extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 			     int buflen);
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCHv4 1/1] [RFC] uartclk from serial_core exposed to sysfs
From: Greg KH @ 2012-09-05 20:36 UTC (permalink / raw)
  To: Tomas Hlavacek; +Cc: alan, linux-serial, linux-kernel, marek.vasut
In-Reply-To: <1345401285-14473-1-git-send-email-tmshlvck@gmail.com>

On Sun, Aug 19, 2012 at 08:34:45PM +0200, Tomas Hlavacek wrote:
> Added file /sys/devices/.../tty/ttySX/uartclk to allow reading
> uartclk value in struct uart_port in serial_core via sysfs.
> 
> It simplifies initialization verification of no-name cards that
> have non-standard oscillator speed while having no distinguishing
> PCI IDs to allow autodetection.
> 
> tty_register_device() has been generalized and refactored in order
> to add support for setting drvdata and attribute_group to the device.
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck@gmail.com>

This looks good, but it doesn't apply to my tty-next branch in
linux-next, so I can't apply it.

But, when you redo it, here's one tiny thing to change:

> +/**
> + *	tty_register_device_attr - register a tty device
> + *	@driver: the tty driver that describes the tty device
> + *	@index: the index in the tty driver for this tty device
> + *	@device: a struct device that is associated with this tty device.
> + *		This field is optional, if there is no known struct device
> + *		for this tty device it can be set to NULL safely.
> + *	@drvdata: Driver data to be set to device (NULL = do not touch).
> + *	@attr_grp: Attribute group to be set on device (NULL = do not touch).

No need to mention the NULL thing here, "do not touch" doesn't mean
much to me.

> +	if (attr_grp)
> +		dev->groups = attr_grp;
> +	if (drvdata)
> +		dev_set_drvdata(dev, drvdata);

No need to test for NULL, just set them, it can't really hurt, right?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH v3 20/23] serial: omap: fix software flow control
From: Greg KH @ 2012-09-05 20:27 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar, Vikram Pandita, stable
In-Reply-To: <1345717983-18179-21-git-send-email-balbi@ti.com>

On Thu, Aug 23, 2012 at 01:33:00PM +0300, Felipe Balbi wrote:
> From: Vikram Pandita <vikram.pandita@ti.com>
> 
> Software flow control register bits were not defined correctly.
> 
> Also clarify the IXON and IXOFF logic to reflect what userspace wants.
> 
> Cc: stable@vger.kernel.org
> Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> Signed-off-by: Vikram Pandita <vikram.pandita@ti.com>
> Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Acked-by: Tony Lindgren <tony@atomide.com>
> ---

If this is a stable patch, should it be pulled out and put also in for
3.6?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH v3 03/23] serial: omap: don't access the platform_device
From: Greg KH @ 2012-09-05 20:27 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar
In-Reply-To: <1345717983-18179-4-git-send-email-balbi@ti.com>

On Thu, Aug 23, 2012 at 01:32:43PM +0300, Felipe Balbi wrote:
> The driver doesn't need to know about its platform_device.
> 
> Everything the driver needs can be done through the
> struct device pointer. In case we need to use the
> OMAP-specific PM function pointers, those can make
> sure to find the device's platform_device pointer
> so they can find the struct omap_device through
> pdev->archdata field.
> 
> Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com>
> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Acked-by: Tony Lindgren <tony@atomide.com>

This series fails when applying to my tty-next branch at this patch :(

Care to refresh it, and resend it, with Tony's acks added, so I can
apply it?  Note, I've already applied the first two.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 1/2] serial: New serial driver SCCNXP
From: Greg Kroah-Hartman @ 2012-09-05 20:24 UTC (permalink / raw)
  To: Alexander Shiyan; +Cc: linux-serial, Alan Cox
In-Reply-To: <1345908260-6948-1-git-send-email-shc_work@mail.ru>

On Sat, Aug 25, 2012 at 07:24:19PM +0400, Alexander Shiyan wrote:
> This driver is a replacement for a SC26XX driver with a lot of
> improvements and new features.
> The main differences from the SC26XX driver:
> - Removed dependency on MIPS. Driver can be used on any platform.
> - Added support for SCC2681, SCC2691, SCC2692, SC28L91, SC28L92,
>   SC28L202, SCC68681 and SCC68692 ICs.
> - Using devm_-related functions.
> - Improved error handling of serial port, improved FIFO handling.
> - Ability to load multiple instances of drivers.
> 
> To avoid the possibility of regression, driver SC26XX left in the
> system to confirm the stability of the driver on platforms where
> it is being used.
> 
> Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
> Acked-by: Alan Cox <alan@linux.intel.com>
> ---
>  drivers/tty/serial/Kconfig           |   18 +
>  drivers/tty/serial/Makefile          |    1 +
>  drivers/tty/serial/sccnxp.c          |  985 ++++++++++++++++++++++++++++++++++
>  include/linux/platform_data/sccnxp.h |   93 ++++
>  4 files changed, 1097 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/tty/serial/sccnxp.c
>  create mode 100644 include/linux/platform_data/sccnxp.h
> 
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 4720b4b..750671d 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1104,6 +1104,24 @@ config SERIAL_SC26XX_CONSOLE
>  	help
>  	  Support for Console on SC2681/SC2692 serial ports.
>  
> +config SERIAL_SCCNXP
> +	bool "SCCNXP serial port support"
> +	depends on !SERIAL_SC26XX
> +	select SERIAL_CORE
> +	default n
> +	help
> +	  This selects support for an advanced UART from NXP (Philips).
> +	  Supported ICs are SCC2681, SCC2691, SCC2692, SC28L91, SC28L92,
> +	  SC28L202, SCC68681 and SCC68692.
> +	  Positioned as a replacement for the driver SC26XX.

This driver can be built as a module, right?  If so, please change this
to a tristate variable, not a "bool".  I don't feel like always building
it into my kernels :)

Care to send a follow-on patch fixing this up?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH] serial: Remove orphaned header sc26198.h
From: Greg Kroah-Hartman @ 2012-09-05 20:20 UTC (permalink / raw)
  To: Paul Bolle; +Cc: Alexander Shiyan, linux-serial, linux-kernel, Alan Cox
In-Reply-To: <1345567392.4564.30.camel@x61.thuisdomein>

On Tue, Aug 21, 2012 at 06:43:12PM +0200, Paul Bolle wrote:
> On Tue, 2012-08-21 at 19:49 +0400, Alexander Shiyan wrote:
> > This header was used by the driver "stallion", but the driver has
> > been removed as a result of migration 2.4 -> 2.6 and the header is
> > still present in the system and is not currently used by any driver.
> > We can safely remove it.
> > 
> > Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
> > ---
> >  include/linux/sc26198.h |  533 -----------------------------------------------
> 
> commit afbaade3dc99838a0c39699bea175674f27322a1 ("delete seven tty
> headers"), in - I think - tty.git's tty-next branch, already deleted
> this and six other headers.

Yes, this patch doesn't apply to the tty-next branch for that very
reason.

In the future Alexander, please try working off of the linux-next tree,
that's the best place for stuff like this.

greg k-h

^ permalink raw reply

* Re: [PATCH v3 00/23] OMAP UART patches
From: Greg KH @ 2012-09-05 20:18 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: alan, Tony Lindgren, Kevin Hilman, Linux OMAP Mailing List,
	Linux ARM Kernel Mailing List, linux-serial,
	Linux Kernel Mailing List, Santosh Shilimkar, Shubhrajyoti Datta,
	Sourav Poddar
In-Reply-To: <20120904114540.GF12901@arwen.pp.htv.fi>

On Tue, Sep 04, 2012 at 02:45:41PM +0300, Felipe Balbi wrote:
> Hi,
> 
> On Fri, Aug 24, 2012 at 01:40:47PM +0300, Felipe Balbi wrote:
> > Forgot to Cc greg initially, my bad
> 
> a gentle ping on this series so we don't miss it for v3.7 merge window.
> 
> Greg, let me know if you need me to resend.

No need, sorry, was on vacation and then the Kernel summit.  I'll get to
these now...

greg k-h

^ permalink raw reply

* Re: Driver for SPI-based 8250 serial port
From: Arnout Vandecappelle @ 2012-09-05 16:29 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-serial
In-Reply-To: <20120905141218.7556f902@pyramind.ukuu.org.uk>

On 09/05/12 15:12, Alan Cox wrote:
>> >  - Should I add a UPIO_SPI to the global I/O types, or should I override the
>> >  serial_in/serial_out functions in struct plat_serial8250_port?
> I am not sure you'll make the 8250 driver handle the device because I
> suspect a lot of the serial_in/serial_out calls occur with interrupts
> disabled on the assumption that they are basically atomic fast operations.

  Argh, that's right.

  So it will be a completely new driver then.  Using the tty layer directly seems
to be a good suggestion: it looks like the uart layer (like the 8250 driver) is
carrying a lot of cruft for supporting all those quirks in the different devices.

  ifx6x60 looks like a good source of inspiration.


  Regards,
  Arnout
-- 
Arnout Vandecappelle                               arnout at mind be
Senior Embedded Software Architect                 +32-16-286540
Essensium/Mind                                     http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium                BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F

^ permalink raw reply

* Re: Driver for SPI-based 8250 serial port
From: Alan Cox @ 2012-09-05 13:12 UTC (permalink / raw)
  To: Arnout Vandecappelle; +Cc: linux-serial
In-Reply-To: <504749CF.50709@mind.be>

> - I guess I should preferably write it as generically as possible, even though
> I can test it on only one device?

There is a balance between making it generic and getting it done and
useful. I would say it is more important to make it possible for someone
else to make it also handle their hardware than attempt to guess what is
needed. Make it possible, but don't do the work.

> - Should I add a UPIO_SPI to the global I/O types, or should I override the
> serial_in/serial_out functions in struct plat_serial8250_port?

I am not sure you'll make the 8250 driver handle the device because I
suspect a lot of the serial_in/serial_out calls occur with interrupts
disabled on the assumption that they are basically atomic fast operations.

> - I guess there should be a 8250_spi file that registers the platform
> device?

Probably, but also allowing people to create those platform devices in
their architecture code or via firmware.

> - I guess it doesn't make sense to try autoconfig_irq for such a device?
> The IRQ is typically a gpio which the platform code has to configure as an IRQ.

Agreed. autoconfigure IRQ really only applies for PC ISA bus type
devices. Most sane architectures know the IRQ to use.

> - I'm not sure how to set the uartclk. The XR20M1280's BRG is derived from a
> 24MHz clock, but other devices or other boards may have different values.
> Should it be part of platform data?  Should I define a new platform data struct
> for that?

platform data would be my guess.

>   Any other suggestions are also welcome.

Take a look at the locking assumptions of 8250.c. If they make it hard to
do the spi driver that way then I would suggest doing a small, clean
platform driver specifically for 16C950 over SPI. Pass the device type
(even if only 950 is supported), baud rate in via the platform struct.
That way others can tackle extending it for different devices as they
need.

Architecturally I think that will be what is needed - you end up wanting
a threaded IRQ handler and other major design differences the moment your
register writes are asynchronous and slow. You may well find that the
uart layer isn't a help either and it's best to go straight from the
tty/tty_port helpers.

Alan

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox