* Re: [PATCH] serial/efm32: add new driver
From: Uwe Kleine-König @ 2011-12-22 8:57 UTC (permalink / raw)
To: Alan Cox
Cc: linux-kernel, devicetree-discuss, Greg Kroah-Hartman,
linux-serial, kernel
In-Reply-To: <20111221202847.4ffeba10@bob.linux.org.uk>
Hello,
On Wed, Dec 21, 2011 at 08:28:47PM +0000, Alan Cox wrote:
> On Wed, 21 Dec 2011 16:05:59 +0100
> Uwe Kleine-König <u.kleine-koenig@pengutronix.de> wrote:
>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> >
> > note that ARCH_EFM32 isn't in mainline yet, so to be actually usable
> > some arch patches are needed.
>
> Start by running it through the CodingStyle scripts as I see a //
> comment in there 8)
oops
> > +static void efm32_usart_rx_chars(struct efm32_usart_port *efm_port)
> > +{
> > + struct uart_port *port = &efm_port->port;
> > + struct tty_struct *tty = port->state->port.tty;
>
> Needs to be using krefs and checking the tty is not NULL
> (tty_port_tty_get)
ah, I copied from mxs-auart. Will try to find a better example.
> > +static void efm32_usart_set_termios(struct uart_port *port,
> > + struct ktermios *new, struct ktermios *old)
> > +{
> > + struct efm32_usart_port *efm_port = to_efm_port(port);
> > + unsigned long flags;
> > + unsigned baud;
> > + u32 clkdiv;
> > +
> > + /* no modem control lines */
> > + new->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
>
> Minor item - HUPCL shouldn't get cleared - its a request for hangup
> behaviour not a port feature.
ah, I copied that from imx (in an if(0) though).
> > + /* currently only some features are implemented */
> > + new->c_cflag &= ~CSIZE;
> > + new->c_cflag |= CS8;
> > + new->c_cflag |= CSTOPB;
> > + new->c_cflag &= ~PARENB;
>
> If you can do CS8 without parity you can do CS7 with parity.
I sticked to the things I use and tested. According to the manual the
hardware can do 4 up to 16 data bits with and without parity :-)
> > + new->c_iflag = 0;
>
> This seems broken. Lots of the iflgs are user requests and stack
> properties not port features. For example you can do xon/xoff as its
> pure software. As far as I can see you should leave c_iflag alone.
ok.
I will send an update and fix the drivers I copied from.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH] serial/efm32: add new driver
From: Alan Cox @ 2011-12-21 20:28 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: linux-kernel, devicetree-discuss, Greg Kroah-Hartman,
linux-serial, kernel
In-Reply-To: <1324479959-7343-1-git-send-email-u.kleine-koenig@pengutronix.de>
On Wed, 21 Dec 2011 16:05:59 +0100
Uwe Kleine-König <u.kleine-koenig@pengutronix.de> wrote:
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> note that ARCH_EFM32 isn't in mainline yet, so to be actually usable
> some arch patches are needed.
Start by running it through the CodingStyle scripts as I see a //
comment in there 8)
> +static void efm32_usart_rx_chars(struct efm32_usart_port *efm_port)
> +{
> + struct uart_port *port = &efm_port->port;
> + struct tty_struct *tty = port->state->port.tty;
Needs to be using krefs and checking the tty is not NULL
(tty_port_tty_get)
> +static void efm32_usart_set_termios(struct uart_port *port,
> + struct ktermios *new, struct ktermios *old)
> +{
> + struct efm32_usart_port *efm_port = to_efm_port(port);
> + unsigned long flags;
> + unsigned baud;
> + u32 clkdiv;
> +
> + /* no modem control lines */
> + new->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
Minor item - HUPCL shouldn't get cleared - its a request for hangup
behaviour not a port feature.
> + /* currently only some features are implemented */
> + new->c_cflag &= ~CSIZE;
> + new->c_cflag |= CS8;
> + new->c_cflag |= CSTOPB;
> + new->c_cflag &= ~PARENB;
If you can do CS8 without parity you can do CS7 with parity.
> + new->c_iflag = 0;
This seems broken. Lots of the iflgs are user requests and stack
properties not port features. For example you can do xon/xoff as its
pure software. As far as I can see you should leave c_iflag alone.
Alan
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] serial/efm32: add new driver
From: Uwe Kleine-König @ 2011-12-21 15:05 UTC (permalink / raw)
To: linux-kernel
Cc: devicetree-discuss, Greg Kroah-Hartman, Alan Cox, linux-serial,
kernel
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,
note that ARCH_EFM32 isn't in mainline yet, so to be actually usable
some arch patches are needed.
Best regards
Uwe
.../devicetree/bindings/tty/serial/efm32-usart.txt | 14 +
drivers/tty/serial/Kconfig | 10 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/efm32-usart.c | 714 ++++++++++++++++++++
include/linux/serial_core.h | 2 +
5 files changed, 741 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/tty/serial/efm32-usart.txt
create mode 100644 drivers/tty/serial/efm32-usart.c
diff --git a/Documentation/devicetree/bindings/tty/serial/efm32-usart.txt b/Documentation/devicetree/bindings/tty/serial/efm32-usart.txt
new file mode 100644
index 0000000..eef2721
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/efm32-usart.txt
@@ -0,0 +1,14 @@
+* Energymicro efm32 UART
+
+Required properties:
+- compatible : Should be "efm32,usart"
+- reg : Address and length of the register set
+- interrupts : Should contain uart interrupt
+
+Example:
+
+uart@0x4000c400 {
+ compatible = "efm32,usart";
+ reg = <0x4000c400 0x400>;
+ interrupts = <15>;
+};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 925a1e5..cfeb0f3 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1610,4 +1610,14 @@ config SERIAL_XILINX_PS_UART_CONSOLE
help
Enable a Xilinx PS UART port to be the system console.
+config SERIAL_EFM32_USART
+ bool "EFM32 USART port."
+ depends on ARCH_EFM32
+ select SERIAL_CORE
+
+config SERIAL_EFM32_USART_CONSOLE
+ bool "EFM32 USART console support"
+ depends on SERIAL_EFM32_USART=y
+ select SERIAL_CORE_CONSOLE
+
endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index e10cf5b..d3ab42b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -94,3 +94,4 @@ obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
+obj-$(CONFIG_SERIAL_EFM32_USART) += efm32-usart.o
diff --git a/drivers/tty/serial/efm32-usart.c b/drivers/tty/serial/efm32-usart.c
new file mode 100644
index 0000000..4d0b636
--- /dev/null
+++ b/drivers/tty/serial/efm32-usart.c
@@ -0,0 +1,714 @@
+#include <linux/kernel.h>
+#include <linux/serial_core.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#define DRIVER_NAME "efm32-usart"
+#define DEV_NAME "ttyefm"
+
+#define USARTn_CTRL 0x00
+#define USARTn_CTRL_SYNC 0x0001
+
+#define USARTn_FRAME 0x04
+#define USARTn_FRAME_DATABITS(n) ((n) - 3)
+#define USARTn_FRAME_PARITY_NONE 0x0000
+#define USARTn_FRAME_STOPBITS_HALF 0x0000
+#define USARTn_FRAME_STOPBITS_ONE 0x1000
+#define USARTn_FRAME_STOPBITS_TWO 0x3000
+
+#define USARTn_CMD 0x0c
+#define USARTn_CMD_RXEN 0x0001
+#define USARTn_CMD_RXDIS 0x0002
+#define USARTn_CMD_TXEN 0x0004
+#define USARTn_CMD_TXDIS 0x0008
+
+#define USARTn_STATUS 0x10
+#define USARTn_STATUS_TXENS 0x0002
+#define USARTn_STATUS_TXC 0x0020
+#define USARTn_STATUS_TXBL 0x0040
+#define USARTn_STATUS_RXDATAV 0x0080
+
+#define USARTn_CLKDIV 0x14
+
+#define USARTn_RXDATAX 0x18
+#define USARTn_RXDATAX_PERR 0x4000
+#define USARTn_RXDATAX_FERR 0x8000
+
+#define USARTn_TXDATA 0x34
+
+#define USARTn_IF 0x40
+#define USARTn_IF_TXBL 0x0002
+#define USARTn_IF_RXDATAV 0x0004
+
+#define USARTn_IFS 0x44
+#define USARTn_IFC 0x48
+#define USARTn_IEN 0x4c
+
+#define USARTn_ROUTE 0x54
+#define USARTn_ROUTE_RXPEN 0x0001
+#define USARTn_ROUTE_TXPEN 0x0002
+
+struct efm32_usart_port {
+ struct uart_port port;
+ unsigned int txirq;
+ struct clk *clk;
+};
+#define to_efm_port(_port) container_of(_port, struct efm32_usart_port, port)
+#define efm_debug(efm_port, format, arg...) \
+ dev_dbg(efm_port->port.dev, format, ##arg)
+
+static void efm32_usart_write32(struct efm32_usart_port *efm_port,
+ u32 value, unsigned offset)
+{
+ __raw_writel(value, efm_port->port.membase + offset);
+}
+
+static u32 efm32_usart_read32(struct efm32_usart_port *efm_port,
+ unsigned offset)
+{
+ return __raw_readl(efm_port->port.membase + offset);
+}
+
+static unsigned int efm32_usart_tx_empty(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ u32 status = efm32_usart_read32(efm_port, USARTn_STATUS);
+
+ /* XXX: does TXBL also mean that the shifter is done? */
+ if (status & USARTn_STATUS_TXBL)
+ return TIOCSER_TEMT;
+ else
+ return 0;
+}
+
+static void efm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* sorry, neither handshaking lines nor loop functionallity */
+}
+
+static unsigned int efm32_usart_get_mctrl(struct uart_port *port)
+{
+ /* sorry, no handshaking lines available */
+ return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR;
+}
+
+static void efm32_usart_stop_tx(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ u32 ien = efm32_usart_read32(efm_port, USARTn_IEN);
+
+ //efm32_usart_write32(efm_port, USARTn_CMD_TXDIS, USARTn_CMD);
+ efm32_usart_write32(efm_port, ien & ~USARTn_IF_TXBL, USARTn_IEN);
+}
+
+static void efm32_usart_tx_chars(struct efm32_usart_port *efm_port)
+{
+ struct uart_port *port = &efm_port->port;
+ struct circ_buf *xmit = &port->state->xmit;
+
+ while (efm32_usart_read32(efm_port, USARTn_STATUS) &
+ USARTn_STATUS_TXBL) {
+ if (port->x_char) {
+ port->icount.tx++;
+ efm32_usart_write32(efm_port, port->x_char,
+ USARTn_TXDATA);
+ port->x_char = 0;
+ continue;
+ }
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
+ port->icount.tx++;
+ efm32_usart_write32(efm_port, xmit->buf[xmit->tail],
+ USARTn_TXDATA);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ } else
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (!port->x_char && uart_circ_empty(xmit))
+ efm32_usart_stop_tx(port);
+}
+
+static void efm32_usart_start_tx(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ u32 ien;
+
+ efm32_usart_write32(efm_port, USARTn_IF_TXBL, USARTn_IFC);
+ ien = efm32_usart_read32(efm_port, USARTn_IEN);
+ efm32_usart_write32(efm_port, ien | USARTn_IF_TXBL, USARTn_IEN);
+ efm32_usart_write32(efm_port, USARTn_CMD_TXEN, USARTn_CMD);
+
+ efm32_usart_tx_chars(efm_port);
+}
+
+static void efm32_usart_stop_rx(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+
+ efm32_usart_write32(efm_port, USARTn_CMD_RXDIS, USARTn_CMD);
+}
+
+static void efm32_usart_enable_ms(struct uart_port *port)
+{
+ /* no handshake lines, no modem status interrupts */
+}
+
+static void efm32_usart_break_ctl(struct uart_port *port, int ctl)
+{
+ /* not possible without fiddling with gpios */
+}
+
+static void efm32_usart_rx_chars(struct efm32_usart_port *efm_port)
+{
+ struct uart_port *port = &efm_port->port;
+ struct tty_struct *tty = port->state->port.tty;
+
+ spin_lock(&port->lock);
+
+ while (efm32_usart_read32(efm_port, USARTn_STATUS) &
+ USARTn_STATUS_RXDATAV) {
+ u32 rxdata = efm32_usart_read32(efm_port, USARTn_RXDATAX);
+ int flag = 0;
+
+ port->icount.rx++;
+
+ /* XXX detect BREAK and overrun */
+
+ if (rxdata & USARTn_RXDATAX_PERR) {
+ port->icount.parity++;
+ if (port->read_status_mask & USARTn_RXDATAX_PERR)
+ flag = TTY_PARITY;
+ } else if (rxdata & USARTn_RXDATAX_FERR) {
+ port->icount.frame++;
+ if (port->read_status_mask & USARTn_RXDATAX_FERR)
+ flag = TTY_FRAME;
+ }
+
+ if (rxdata & port->ignore_status_mask)
+ continue;
+
+ tty_insert_flip_char(tty, rxdata, flag);
+ }
+ spin_unlock(&port->lock);
+
+ tty_flip_buffer_push(tty);
+}
+
+static irqreturn_t efm32_usart_rxirq(int irq, void *data)
+{
+ struct efm32_usart_port *efm_port = data;
+ u32 irqflag = efm32_usart_read32(efm_port, USARTn_IF);
+
+ if (irqflag & USARTn_IF_RXDATAV) {
+ efm32_usart_write32(efm_port, USARTn_IF_RXDATAV, USARTn_IFC);
+ efm32_usart_rx_chars(efm_port);
+
+ return IRQ_HANDLED;
+ } else
+ return IRQ_NONE;
+}
+
+static irqreturn_t efm32_usart_txirq(int irq, void *data)
+{
+ struct efm32_usart_port *efm_port = data;
+ u32 irqflag = efm32_usart_read32(efm_port, USARTn_IF);
+
+ if (irqflag & USARTn_IF_TXBL) {
+ efm32_usart_write32(efm_port, USARTn_IF_TXBL, USARTn_IFC);
+ efm32_usart_tx_chars(efm_port);
+ return IRQ_HANDLED;
+ } else
+ return IRQ_NONE;
+}
+
+static int efm32_usart_startup(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ int ret;
+
+ ret = clk_enable(efm_port->clk);
+ if (ret) {
+ efm_debug(efm_port, "failed to enable clk\n");
+ goto err_clk_enable;
+ }
+ port->uartclk = clk_get_rate(efm_port->clk);
+
+ /* Enable pins at default location */
+ efm32_usart_write32(efm_port, USARTn_ROUTE_RXPEN | USARTn_ROUTE_TXPEN,
+ USARTn_ROUTE);
+
+ ret = request_irq(port->irq, efm32_usart_rxirq, 0,
+ DRIVER_NAME, efm_port);
+ if (ret) {
+ efm_debug(efm_port, "failed to register rxirq\n");
+ goto err_request_irq_rx;
+ }
+
+ /* disable all irqs */
+ efm32_usart_write32(efm_port, 0, USARTn_IEN);
+
+ ret = request_irq(efm_port->txirq, efm32_usart_txirq, 0,
+ DRIVER_NAME, efm_port);
+ if (ret) {
+ efm_debug(efm_port, "failed to register txirq\n");
+ free_irq(port->irq, efm_port);
+err_request_irq_rx:
+
+ clk_disable(efm_port->clk);
+ } else {
+ efm32_usart_write32(efm_port, USARTn_IF_RXDATAV, USARTn_IEN);
+ efm32_usart_write32(efm_port, USARTn_CMD_RXEN, USARTn_CMD);
+ }
+
+err_clk_enable:
+ return ret;
+}
+
+static void efm32_usart_shutdown(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+
+ efm32_usart_write32(efm_port, 0, USARTn_IEN);
+ free_irq(port->irq, efm_port);
+
+ clk_disable(efm_port->clk);
+}
+
+static void efm32_usart_set_termios(struct uart_port *port,
+ struct ktermios *new, struct ktermios *old)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ unsigned long flags;
+ unsigned baud;
+ u32 clkdiv;
+
+ /* no modem control lines */
+ new->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
+
+ /* currently only some features are implemented */
+ new->c_cflag &= ~CSIZE;
+ new->c_cflag |= CS8;
+ new->c_cflag |= CSTOPB;
+ new->c_cflag &= ~PARENB;
+ new->c_iflag = 0;
+
+ baud = uart_get_baud_rate(port, new, old,
+ DIV_ROUND_CLOSEST(port->uartclk, 16 * 8192),
+ DIV_ROUND_CLOSEST(port->uartclk, 16));
+
+ /*
+ * the 6 lowest bits of CLKDIV are dc, bit 6 has value 0.25.
+ * port->uartclk <= 14e6, so 4 * port->uartclk doesn't overflow.
+ */
+ clkdiv = (DIV_ROUND_CLOSEST(4 * port->uartclk, 16 * baud) - 4) << 6;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ efm32_usart_write32(efm_port,
+ USARTn_CMD_TXDIS | USARTn_CMD_RXDIS, USARTn_CMD);
+
+ port->read_status_mask = 0;
+ port->ignore_status_mask = 0;
+
+ uart_update_timeout(port, new->c_cflag, baud);
+
+ efm32_usart_write32(efm_port, 0, USARTn_CTRL);
+ efm32_usart_write32(efm_port, USARTn_FRAME_STOPBITS_ONE |
+ USARTn_FRAME_PARITY_NONE | USARTn_FRAME_DATABITS(8),
+ USARTn_FRAME);
+ efm32_usart_write32(efm_port, clkdiv, USARTn_CLKDIV);
+
+ efm32_usart_write32(efm_port, USARTn_CMD_TXEN | USARTn_CMD_RXEN, USARTn_CMD);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *efm32_usart_type(struct uart_port *port)
+{
+ return port->type == PORT_EFMUSART ? "efm32-usart" : NULL;
+}
+
+static void efm32_usart_release_port(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+
+ clk_unprepare(efm_port->clk);
+ clk_put(efm_port->clk);
+ iounmap(port->membase);
+}
+
+static int efm32_usart_request_port(struct uart_port *port)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ int ret;
+
+ port->membase = ioremap(port->mapbase, 60);
+ if (!efm_port->port.membase) {
+ ret = -ENOMEM;
+ efm_debug(efm_port, "failed to remap\n");
+ goto err_ioremap;
+ }
+
+ efm_port->clk = clk_get(port->dev, NULL);
+ if (IS_ERR(efm_port->clk)) {
+ ret = PTR_ERR(efm_port->clk);
+ efm_debug(efm_port, "failed to get clock\n");
+ goto err_clk_get;
+ }
+
+ ret = clk_prepare(efm_port->clk);
+ if (ret) {
+ clk_put(efm_port->clk);
+err_clk_get:
+
+ iounmap(port->membase);
+err_ioremap:
+ return ret;
+ }
+ return 0;
+}
+
+static void efm32_usart_config_port(struct uart_port *port, int type)
+{
+ if (type & UART_CONFIG_TYPE &&
+ !efm32_usart_request_port(port))
+ port->type = PORT_EFMUSART;
+}
+
+static int efm32_usart_verify_port(struct uart_port *port,
+ struct serial_struct *serinfo)
+{
+ int ret = 0;
+
+ if (serinfo->type != PORT_UNKNOWN && serinfo->type != PORT_EFMUSART)
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static struct uart_ops efm32_usart_pops = {
+ .tx_empty = efm32_usart_tx_empty,
+ .set_mctrl = efm32_usart_set_mctrl,
+ .get_mctrl = efm32_usart_get_mctrl,
+ .stop_tx = efm32_usart_stop_tx,
+ .start_tx = efm32_usart_start_tx,
+ .stop_rx = efm32_usart_stop_rx,
+ .enable_ms = efm32_usart_enable_ms,
+ .break_ctl = efm32_usart_break_ctl,
+ .startup = efm32_usart_startup,
+ .shutdown = efm32_usart_shutdown,
+ .set_termios = efm32_usart_set_termios,
+ .type = efm32_usart_type,
+ .release_port = efm32_usart_release_port,
+ .request_port = efm32_usart_request_port,
+ .config_port = efm32_usart_config_port,
+ .verify_port = efm32_usart_verify_port,
+};
+
+static struct efm32_usart_port *efm32_usart_ports[3];
+
+#ifdef CONFIG_SERIAL_EFM32_USART_CONSOLE
+static void efm32_usart_console_putchar(struct uart_port *port, int ch)
+{
+ struct efm32_usart_port *efm_port = to_efm_port(port);
+ unsigned int timeout = 0x400;
+ u32 status;
+
+ while (1) {
+ status = efm32_usart_read32(efm_port, USARTn_STATUS);
+
+ if (status & USARTn_STATUS_TXBL)
+ break;
+ if (!timeout--)
+ return;
+ }
+ efm32_usart_write32(efm_port, ch, USARTn_TXDATA);
+}
+
+static void efm32_usart_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct efm32_usart_port *efm_port = efm32_usart_ports[co->index];
+ u32 status = efm32_usart_read32(efm_port, USARTn_STATUS);
+ unsigned int timeout = 0x400;
+
+ if (!(status & USARTn_STATUS_TXENS))
+ efm32_usart_write32(efm_port, USARTn_CMD_TXEN, USARTn_CMD);
+
+ uart_console_write(&efm_port->port, s, count,
+ efm32_usart_console_putchar);
+
+ /* Wait for the transmitter to become empty */
+ while (1) {
+ u32 status = efm32_usart_read32(efm_port, USARTn_STATUS);
+ if (status & USARTn_STATUS_TXC)
+ break;
+ if (!timeout--)
+ break;
+ }
+
+ if (!(status & USARTn_STATUS_TXENS))
+ efm32_usart_write32(efm_port, USARTn_CMD_TXDIS, USARTn_CMD);
+}
+
+static void efm32_usart_console_get_options(struct efm32_usart_port *efm_port,
+ int *baud, int *parity, int *bits)
+{
+ u32 ctrl = efm32_usart_read32(efm_port, USARTn_CTRL);
+ u32 route, clkdiv;
+
+ if (ctrl & USARTn_CTRL_SYNC)
+ /* not operating in async mode */
+ return;
+
+ route = efm32_usart_read32(efm_port, USARTn_ROUTE);
+ if (!(route & USARTn_ROUTE_TXPEN))
+ /* tx pin not routed */
+ return;
+
+ clkdiv = efm32_usart_read32(efm_port, USARTn_CLKDIV);
+
+ *baud = DIV_ROUND_CLOSEST(4 * efm_port->port.uartclk,
+ 16 * (4 + (clkdiv >> 6)));
+ *parity = 'n';
+ *bits = 8;
+
+ efm_debug(efm_port, "get_opts: baud=%d\n", *baud);
+}
+
+static int efm32_usart_console_setup(struct console *co, char *options)
+{
+ struct efm32_usart_port *efm_port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ int ret;
+
+ if (co->index < 0 || co->index >= ARRAY_SIZE(efm32_usart_ports)) {
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(efm32_usart_ports); ++i) {
+ if (efm32_usart_ports[i]) {
+ pr_warn("efm32-console: fall back to console index %u (from %hhi)\n",
+ i, co->index);
+ co->index = i;
+ break;
+ }
+ }
+ }
+
+ efm_port = efm32_usart_ports[co->index];
+ if (!efm_port) {
+ pr_warn("efm32-console: No port at %d\n", co->index);
+ return -ENODEV;
+ }
+
+ ret = clk_prepare(efm_port->clk);
+ if (ret) {
+ dev_warn(efm_port->port.dev,
+ "console: clk_prepare failed: %d\n", ret);
+ return ret;
+ }
+
+ efm_port->port.uartclk = clk_get_rate(efm_port->clk);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ efm32_usart_console_get_options(efm_port,
+ &baud, &parity, &bits);
+
+ return uart_set_options(&efm_port->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver efm32_usart_reg;
+
+static struct console efm32_usart_console = {
+ .name = DEV_NAME,
+ .write = efm32_usart_console_write,
+ .device = uart_console_device,
+ .setup = efm32_usart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &efm32_usart_reg,
+};
+
+#else
+#define efm32_usart_console (*(struct console *)NULL)
+#endif /* ifdef CONFIG_SERIAL_EFM32_USART_CONSOLE / else */
+
+static struct uart_driver efm32_usart_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = DEV_NAME,
+ .nr = ARRAY_SIZE(efm32_usart_ports),
+ .cons = &efm32_usart_console,
+};
+
+static int efm32_usart_probe_dt(struct platform_device *pdev,
+ struct efm32_usart_port *efm_port)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ if (!np)
+ return 1;
+
+ ret = of_alias_get_id(np, "serial");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to get alias id: %d\n", ret);
+ return ret;
+ } else {
+ efm_port->port.line = ret;
+ return 0;
+ }
+
+}
+
+static int __devinit efm32_usart_probe(struct platform_device *pdev)
+{
+ struct efm32_usart_port *efm_port;
+ struct resource *res;
+ int ret;
+
+ efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL);
+ if (!efm_port) {
+ dev_dbg(&pdev->dev, "failed to allocate private data\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ dev_dbg(&pdev->dev, "failed to determine base address\n");
+ goto err_get_base;
+ }
+
+ if (resource_size(res) < 60) {
+ ret = -EINVAL;
+ dev_dbg(&pdev->dev, "memory resource too small\n");
+ goto err_too_small;
+ }
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_dbg(&pdev->dev, "failed to get rx irq\n");
+ goto err_get_rxirq;
+ }
+
+ efm_port->port.irq = ret;
+
+ ret = platform_get_irq(pdev, 1);
+ if (ret <= 0)
+ ret = efm_port->port.irq + 1;
+
+ efm_port->txirq = ret;
+
+ efm_port->port.dev = &pdev->dev;
+ efm_port->port.mapbase = res->start;
+ efm_port->port.type = PORT_EFMUSART;
+ efm_port->port.iotype = UPIO_MEM32;
+ efm_port->port.fifosize = 2;
+ efm_port->port.ops = &efm32_usart_pops;
+ efm_port->port.flags = UPF_BOOT_AUTOCONF;
+
+ ret = efm32_usart_probe_dt(pdev, efm_port);
+ if (ret > 0)
+ /* not created by device tree */
+ efm_port->port.line = pdev->id;
+
+ if (efm_port->port.line >= 0 &&
+ efm_port->port.line < ARRAY_SIZE(efm32_usart_ports))
+ efm32_usart_ports[efm_port->port.line] = efm_port;
+
+ ret = uart_add_one_port(&efm32_usart_reg, &efm_port->port);
+ if (ret) {
+ dev_dbg(&pdev->dev, "failed to add port: %d\n", ret);
+
+ if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_usart_ports))
+ efm32_usart_ports[pdev->id] = NULL;
+err_get_rxirq:
+err_too_small:
+err_get_base:
+ kfree(efm_port);
+ } else {
+ platform_set_drvdata(pdev, efm_port);
+ dev_dbg(&pdev->dev, "\\o/\n");
+ }
+
+ return ret;
+}
+
+static int __devexit efm32_usart_remove(struct platform_device *pdev)
+{
+ struct efm32_usart_port *efm_port = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ uart_remove_one_port(&efm32_usart_reg, &efm_port->port);
+
+ if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_usart_ports))
+ efm32_usart_ports[pdev->id] = NULL;
+
+ kfree(efm_port);
+
+ return 0;
+}
+
+static struct of_device_id efm32_usart_dt_ids[] = {
+ {
+ .compatible = "efm32,usart",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, efm32_usart_dt_ids);
+
+static struct platform_driver efm32_usart_driver = {
+ .probe = efm32_usart_probe,
+ .remove = __devexit_p(efm32_usart_remove),
+
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = efm32_usart_dt_ids,
+ },
+};
+
+static int __init efm32_usart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&efm32_usart_reg);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&efm32_usart_driver);
+ if (ret)
+ uart_unregister_driver(&efm32_usart_reg);
+
+ pr_info("EFM32 USART driver\n");
+
+ return ret;
+}
+module_init(efm32_usart_init);
+
+static void __exit efm32_usart_exit(void)
+{
+ platform_driver_unregister(&efm32_usart_driver);
+ uart_unregister_driver(&efm32_usart_reg);
+}
+
+MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
+MODULE_DESCRIPTION("EFM32 USART driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index eadf33d..eb45d4d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -207,6 +207,8 @@
/* Xilinx PSS UART */
#define PORT_XUARTPS 98
+#define PORT_EFMUSART 99
+
#ifdef __KERNEL__
#include <linux/compiler.h>
--
1.7.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH V2] omap-serial: add RS485 mode support
From: Ilya Yanok @ 2011-12-20 22:10 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-omap, linux-serial, sasha_d, 'Detlev Zundel',
Wolfgang Denk
In-Reply-To: <20111220215333.GA6775@pengutronix.de>
Hi Wolfram,
On 21.12.2011 01:53, Wolfram Sang wrote:
>> Add support for asserting RTS line while TX is in progress. OMAP
>> hardware doesn't support auto-RS485 mode so we control the line from
>> software. We use TX_EMPTY_CTL_IT bit in SCR register to generate TX
>> empty interrupt.
>
> Sorry to bring bad news, but software RS485 is not mainlinable [1].
> You can browse linux-serial for RS485 to find more threads about it.
I see. Actually I searched the lists and seen that completely software
solution (using timers) was never merged. This is somewhere in between:
hardware can fire an interrupt exactly after both TX FIFO and shift
register are emptied so it's only the interrupt latency that affects the
timing.
Thanks for your reply anyway. We will have to maintain this patch in our
tree then.
Regards, Ilya.
^ permalink raw reply
* Re: [PATCH V2] omap-serial: add RS485 mode support
From: Wolfram Sang @ 2011-12-20 21:53 UTC (permalink / raw)
To: Ilya Yanok; +Cc: linux-omap, linux-serial, sasha_d
In-Reply-To: <1324416212-10012-1-git-send-email-yanok@emcraft.com>
[-- Attachment #1: Type: text/plain, Size: 684 bytes --]
Hi,
On Tue, Dec 20, 2011 at 10:23:32PM +0100, Ilya Yanok wrote:
> Add support for asserting RTS line while TX is in progress. OMAP
> hardware doesn't support auto-RS485 mode so we control the line from
> software. We use TX_EMPTY_CTL_IT bit in SCR register to generate TX
> empty interrupt.
Sorry to bring bad news, but software RS485 is not mainlinable [1].
You can browse linux-serial for RS485 to find more threads about it.
Regards,
Wolfram
[1] http://article.gmane.org/gmane.linux.serial/3619/
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* [PATCH V2] omap-serial: add RS485 mode support
From: Ilya Yanok @ 2011-12-20 21:23 UTC (permalink / raw)
To: linux-omap, linux-serial; +Cc: sasha_d, Ilya Yanok
Add support for asserting RTS line while TX is in progress. OMAP
hardware doesn't support auto-RS485 mode so we control the line from
software. We use TX_EMPTY_CTL_IT bit in SCR register to generate TX
empty interrupt.
We use SER_RS485_RTS_ON_SEND flag to control the polarity of RTS signal
(RTS is asserted high during transmition if this flag is set and low
otherwise) though I'm not sure if this is what this flag is for...
Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
Changes from V1:
- rebased onto current linux-omap/master
arch/arm/plat-omap/include/plat/omap-serial.h | 3 +
drivers/tty/serial/omap-serial.c | 126 ++++++++++++++++++++++---
include/linux/serial_reg.h | 2 +
3 files changed, 118 insertions(+), 13 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 9ff4444..d6f5eee 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -136,6 +136,9 @@ struct uart_omap_port {
u32 latency;
u32 calc_latency;
struct work_struct qos_work;
+ struct serial_rs485 rs485;
+ unsigned int tx_in_progress:1,
+ tx_wait_end:1;
};
#endif /* __OMAP_SERIAL_H__ */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index ca24ab3..1483c43 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -39,12 +39,14 @@
#include <linux/irq.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/uaccess.h>
#include <plat/dma.h>
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
#define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
+#define OMAP_RS485_SUPPORTED (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND)
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
@@ -126,6 +128,45 @@ static void serial_omap_enable_ms(struct uart_port *port)
pm_runtime_put(&up->pdev->dev);
}
+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+}
+
+static inline void serial_omap_disable_ier_thri(struct uart_omap_port *up)
+{
+ if (up->ier & UART_IER_THRI) {
+ up->ier &= ~UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ }
+}
+
+static inline void serial_omap_thri_mode(struct uart_omap_port *up)
+{
+ unsigned char scr = serial_in(up, UART_OMAP_SCR);
+
+ if (up->tx_wait_end)
+ scr |= UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+ else
+ scr &= ~UART_OMAP_SCR_TX_EMPTY_CTL_IT;
+ serial_out(up, UART_OMAP_SCR, scr);
+}
+
+static inline void serial_omap_update_rts(struct uart_omap_port *up)
+{
+ unsigned char mcr = up->mcr;
+ int rts_on_send = up->rs485.flags & SER_RS485_RTS_ON_SEND;
+
+ if ((up->rs485.flags & SER_RS485_ENABLED) &&
+ ((up->tx_in_progress && rts_on_send) ||
+ !(up->tx_in_progress || rts_on_send)))
+ mcr |= UART_MCR_RTS;
+ serial_out(up, UART_MCR, mcr);
+}
+
static void serial_omap_stop_tx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -146,11 +187,13 @@ static void serial_omap_stop_tx(struct uart_port *port)
}
pm_runtime_get_sync(&up->pdev->dev);
- if (up->ier & UART_IER_THRI) {
- up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
+ if (!(up->rs485.flags & SER_RS485_ENABLED)) {
+ serial_omap_disable_ier_thri(up);
+ } else {
+ up->tx_wait_end = 1;
+ serial_omap_thri_mode(up);
+ serial_omap_enable_ier_thri(up);
}
-
pm_runtime_mark_last_busy(&up->pdev->dev);
pm_runtime_put_autosuspend(&up->pdev->dev);
}
@@ -268,14 +311,6 @@ static void transmit_chars(struct uart_omap_port *up)
serial_omap_stop_tx(&up->port);
}
-static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
-{
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
- }
-}
-
static void serial_omap_start_tx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
@@ -283,6 +318,18 @@ static void serial_omap_start_tx(struct uart_port *port)
unsigned int start;
int ret = 0;
+ if (up->rs485.flags & SER_RS485_ENABLED) {
+ if (!up->tx_in_progress) {
+ up->tx_in_progress = 1;
+ serial_omap_update_rts(up);
+ }
+ if (up->tx_wait_end) {
+ up->tx_wait_end = 0;
+ serial_omap_thri_mode(up);
+ serial_omap_disable_ier_thri(up);
+ }
+ }
+
if (!up->use_dma) {
pm_runtime_get_sync(&up->pdev->dev);
serial_omap_enable_ier_thri(up);
@@ -369,6 +416,11 @@ static unsigned int check_modem_status(struct uart_omap_port *up)
return status;
}
+static inline unsigned int __serial_omap_tx_empty(struct uart_omap_port *up)
+{
+ return serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+}
+
/**
* serial_omap_irq() - This handles the interrupt from one port
* @irq: uart port irq number
@@ -389,6 +441,17 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
}
spin_lock_irqsave(&up->port.lock, flags);
+ if (up->tx_wait_end && (iir & UART_IIR_THRI) &&
+ __serial_omap_tx_empty(up)) {
+ up->tx_wait_end = 0;
+ up->tx_in_progress = 0;
+ serial_omap_thri_mode(up);
+ serial_omap_update_rts(up);
+ serial_omap_disable_ier_thri(up);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return IRQ_HANDLED;
+ }
+
lsr = serial_in(up, UART_LSR);
if (iir & UART_IIR_RLSI) {
if (!up->use_dma) {
@@ -424,7 +487,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
pm_runtime_get_sync(&up->pdev->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;
+ ret = __serial_omap_tx_empty(up);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_put(&up->pdev->dev);
return ret;
@@ -1128,6 +1191,42 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
#endif
+static int
+serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
+{
+ struct serial_rs485 rs485conf;
+ struct uart_omap_port *up = (struct uart_omap_port *)port;
+ unsigned long flags;
+
+ switch (cmd) {
+ case TIOCSRS485:
+ if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
+ sizeof(rs485conf)))
+ return -EFAULT;
+
+ rs485conf.flags &= OMAP_RS485_SUPPORTED;
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (!(rs485conf.flags & SER_RS485_ENABLED)) {
+ up->tx_in_progress = 0;
+ up->tx_wait_end = 0;
+ }
+ up->rs485 = rs485conf;
+ serial_omap_update_rts(up);
+ serial_omap_thri_mode(up);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ case TIOCGRS485:
+ if (copy_to_user((struct serial_rs485 *) arg,
+ &(up->rs485), sizeof(rs485conf)))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
static struct uart_ops serial_omap_pops = {
.tx_empty = serial_omap_tx_empty,
.set_mctrl = serial_omap_set_mctrl,
@@ -1141,6 +1240,7 @@ static struct uart_ops serial_omap_pops = {
.shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios,
.pm = serial_omap_pm,
+ .ioctl = serial_omap_ioctl,
.type = serial_omap_type,
.release_port = serial_omap_release_port,
.request_port = serial_omap_request_port,
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 8ce70d7..8c1083c 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -363,5 +363,7 @@
#define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */
#define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */
+#define UART_OMAP_SCR_TX_EMPTY_CTL_IT 0x04 /* TX Empty IRQ mode */
+
#endif /* _LINUX_SERIAL_REG_H */
--
1.7.6.4
^ permalink raw reply related
* Re: Connecting serial ports back to back.
From: Alan Cox @ 2011-12-20 11:13 UTC (permalink / raw)
To: Subodh Nijsure; +Cc: linux-serial
In-Reply-To: <CAMFeL9JMTo_ms6TUVeA3imqB0iymPONOGk=hBPmmGM2gY1ZArg@mail.gmail.com>
On Mon, 19 Dec 2011 16:15:43 -0800
Subodh Nijsure <nijsure.subodh@gmail.com> wrote:
> I have hardware where we have two ports that need to be connected back
> to back. One serial port is /dev/ttyAPP2 and other is /dev/ttyUSB0
>
> Basically what I want to make happen is data coming from /dev/ttyUSB0
> should be sent to /dev/ttyAPP2 and vice versa.
>
> It appears that I should be able to do this using the n_tracesink and
> n_tracerouter line discipline drivers.
>
> Has anyone been successful in hooking up serial ports back-to-back
> using these two line discipline drivers?
tracerouter/sink are a bit more specialist than that. But for general
data copying you can just run an application to do it.
Alan
^ permalink raw reply
* [PATCH] serial: use DIV_ROUND_CLOSEST instead of open coding it
From: Uwe Kleine-König @ 2011-12-20 10:47 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alan Cox, linux-serial, linux-kernel
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
drivers/tty/serial/serial_core.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0406d7f..a05afc3 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -423,7 +423,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
- quot = (port->uartclk + (8 * baud)) / (16 * baud);
+ quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
return quot;
}
--
1.7.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH V3 10/14] ARM: mxs: add clk_prepare/clk_unprepare
From: Shawn Guo @ 2011-12-20 2:15 UTC (permalink / raw)
To: Richard Zhao, Sascha Hauer
Cc: linux-arm-kernel, linux-i2c, linux-mmc, netdev, linux-serial,
linux, amit.kucheria, kernel, ben-linux, cjb, alan, eric.miao
In-Reply-To: <1321008637-19999-11-git-send-email-richard.zhao@linaro.org>
Hi Sascha,
Can you drop this patch from your tree? This patch is not complete
even for mxs platform/arch code, and will conflict with my mxs
clk-prepare series.
--
Regards,
Shawn
On Fri, Nov 11, 2011 at 06:50:33PM +0800, Richard Zhao wrote:
> Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
> ---
> arch/arm/mach-mxs/system.c | 2 +-
> arch/arm/mach-mxs/timer.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
> index 20ec3bd..9760a12 100644
> --- a/arch/arm/mach-mxs/system.c
> +++ b/arch/arm/mach-mxs/system.c
> @@ -66,7 +66,7 @@ static int __init mxs_arch_reset_init(void)
>
> clk = clk_get_sys("rtc", NULL);
> if (!IS_ERR(clk))
> - clk_enable(clk);
> + clk_prepare_enable(clk);
>
> return 0;
> }
> diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
> index cace0d2..564a632 100644
> --- a/arch/arm/mach-mxs/timer.c
> +++ b/arch/arm/mach-mxs/timer.c
> @@ -245,7 +245,7 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
>
> void __init mxs_timer_init(struct clk *timer_clk, int irq)
> {
> - clk_enable(timer_clk);
> + clk_prepare_enable(timer_clk);
>
> /*
> * Initialize timers to a known state
> --
> 1.7.5.4
^ permalink raw reply
* Re: [PATCH V3 10/14] ARM: mxs: add clk_prepare/clk_unprepare
From: Richard Zhao @ 2011-12-20 0:56 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-arm-kernel, amit.kucheria, linux, kernel, netdev, linux-mmc,
eric.miao, linux-i2c, linux-serial, cjb, Fabio Estevam,
Richard Zhao, ben-linux, alan
In-Reply-To: <201112192321.41560.marek.vasut@gmail.com>
On Mon, Dec 19, 2011 at 11:21:41PM +0100, Marek Vasut wrote:
> > Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
> > ---
> > arch/arm/mach-mxs/system.c | 2 +-
> > arch/arm/mach-mxs/timer.c | 2 +-
> > 2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
> > index 20ec3bd..9760a12 100644
> > --- a/arch/arm/mach-mxs/system.c
> > +++ b/arch/arm/mach-mxs/system.c
> > @@ -66,7 +66,7 @@ static int __init mxs_arch_reset_init(void)
> >
> > clk = clk_get_sys("rtc", NULL);
> > if (!IS_ERR(clk))
> > - clk_enable(clk);
> > + clk_prepare_enable(clk);
> >
> > return 0;
> > }
> > diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
> > index cace0d2..564a632 100644
> > --- a/arch/arm/mach-mxs/timer.c
> > +++ b/arch/arm/mach-mxs/timer.c
> > @@ -245,7 +245,7 @@ static int __init mxs_clocksource_init(struct clk
> > *timer_clk)
> >
> > void __init mxs_timer_init(struct clk *timer_clk, int irq)
> > {
> > - clk_enable(timer_clk);
> > + clk_prepare_enable(timer_clk);
> >
> > /*
> > * Initialize timers to a known state
>
> Hi Richard,
>
> I just came across this, will this also help solve the mxs problem with mutex
> lock begin done in atomic context in clk_enable/disable()?
No, It's for converting to generic clock framwork.
You can look at Mike's generic clock patches. clk_hw_ops.enable/disable
definitely can not sleep.
On register side, there' two way to protect register:
- use a global spin lock
- only use spin lock wherever gate register share the same one with
other non-gate register.
Thanks
Richard
>
> M
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* Connecting serial ports back to back.
From: Subodh Nijsure @ 2011-12-20 0:15 UTC (permalink / raw)
To: linux-serial
I have hardware where we have two ports that need to be connected back
to back. One serial port is /dev/ttyAPP2 and other is /dev/ttyUSB0
Basically what I want to make happen is data coming from /dev/ttyUSB0
should be sent to /dev/ttyAPP2 and vice versa.
It appears that I should be able to do this using the n_tracesink and
n_tracerouter line discipline drivers.
Has anyone been successful in hooking up serial ports back-to-back
using these two line discipline drivers?
/Subodh
^ permalink raw reply
* Re: [PATCH V3 10/14] ARM: mxs: add clk_prepare/clk_unprepare
From: Marek Vasut @ 2011-12-19 22:21 UTC (permalink / raw)
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Richard Zhao, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
amit.kucheria-Z7WLFzj8eWMS+FvcfC7Uqw,
linux-lFZ/pmaqli7XmaaqVzeoHQ, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
eric.miao-QSEj5FYQhm4dnm+yROfE0A,
ben-linux-elnMNo+KYs3YtjvyW6yDsg, cjb-2X9k7bc8m7Mdnm+yROfE0A,
alan-VuQAYsv1563Yd54FQh9/CA, Fabio Estevam
In-Reply-To: <1321008637-19999-11-git-send-email-richard.zhao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Signed-off-by: Richard Zhao <richard.zhao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> arch/arm/mach-mxs/system.c | 2 +-
> arch/arm/mach-mxs/timer.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
> index 20ec3bd..9760a12 100644
> --- a/arch/arm/mach-mxs/system.c
> +++ b/arch/arm/mach-mxs/system.c
> @@ -66,7 +66,7 @@ static int __init mxs_arch_reset_init(void)
>
> clk = clk_get_sys("rtc", NULL);
> if (!IS_ERR(clk))
> - clk_enable(clk);
> + clk_prepare_enable(clk);
>
> return 0;
> }
> diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
> index cace0d2..564a632 100644
> --- a/arch/arm/mach-mxs/timer.c
> +++ b/arch/arm/mach-mxs/timer.c
> @@ -245,7 +245,7 @@ static int __init mxs_clocksource_init(struct clk
> *timer_clk)
>
> void __init mxs_timer_init(struct clk *timer_clk, int irq)
> {
> - clk_enable(timer_clk);
> + clk_prepare_enable(timer_clk);
>
> /*
> * Initialize timers to a known state
Hi Richard,
I just came across this, will this also help solve the mxs problem with mutex
lock begin done in atomic context in clk_enable/disable()?
M
^ permalink raw reply
* Re: [GIT PULL] ARM: amba: Enable module alias autogeneration for AMBA drivers
From: Russell King - ARM Linux @ 2011-12-19 21:39 UTC (permalink / raw)
To: Dave Martin
Cc: Alessandro Rubini, patches, linux-kernel, linux-arm-kernel, alan,
a.zummo, alsa-devel, cjb, dan.j.williams, dmitry.torokhov,
grant.likely, perex, jassisinghbrar, julia, linus.walleij,
linux-fbdev, linux-input, linux-mmc, linux-serial, linux-watchdog,
lethal, Pawel.Moll, rtc-linux, spi-devel-general, tiwai,
vinod.koul, wim
In-Reply-To: <20111219132409.GB2031@linaro.org>
On Mon, Dec 19, 2011 at 01:24:09PM +0000, Dave Martin wrote:
> Hi Russell,
>
> This one isn't urgent, but I'm not seeing the amba modalias patches
> anywhere yet. Did you have any outstanding concerns which need to be
> resolved?
>
> If you can suggest when/if these are likely to merge that would be great.
>
> Since Alessandro is now expecting to have to rebase on top of the amba
> additions anyway, we shouldn't need to worry about conflicting with his
> patches.
>
> Of course, if you've already merged these somewhere, then there's no
> problem.
I have pulled it, I just haven't merged it in anywhere yet.
^ permalink raw reply
* LET US WORK TOGETHER
From: Dr. William Cole @ 2011-12-19 13:39 UTC (permalink / raw)
[-- Attachment #1: Type: text/plain, Size: 145 bytes --]
To ensure that you get this message
I have attached a file to this mail.
Please ensure you read the attached file
and reply as soon as possible
[-- Attachment #2: LET US WORK TOGETHER.rtf --]
[-- Type: application/octet-stream, Size: 3932 bytes --]
^ permalink raw reply
* Re: [GIT PULL] ARM: amba: Enable module alias autogeneration for AMBA drivers
From: Dave Martin @ 2011-12-19 13:24 UTC (permalink / raw)
To: Alessandro Rubini
Cc: linux, patches, linux-kernel, linux-arm-kernel, alan, a.zummo,
alsa-devel, cjb, dan.j.williams, dmitry.torokhov, grant.likely,
perex, jassisinghbrar, julia, linus.walleij, linux-fbdev,
linux-input, linux-mmc, linux-serial, linux-watchdog, lethal,
Pawel.Moll, rtc-linux, spi-devel-general, tiwai, vinod.koul, wim
In-Reply-To: <20111206161815.GD13769@linaro.org>
Hi Russell,
This one isn't urgent, but I'm not seeing the amba modalias patches
anywhere yet. Did you have any outstanding concerns which need to be
resolved?
If you can suggest when/if these are likely to merge that would be great.
Since Alessandro is now expecting to have to rebase on top of the amba
additions anyway, we shouldn't need to worry about conflicting with his
patches.
Of course, if you've already merged these somewhere, then there's no
problem.
Cheers
---Dave
^ permalink raw reply
* Re: [PATCH 1/2] imx: Add save/restore functions for UART control regs
From: Sascha Hauer @ 2011-12-19 10:10 UTC (permalink / raw)
To: Dirk Behme
Cc: Shawn Guo, linux-arm-kernel, Dirk Behme, linux-serial,
Uwe Kleine-König, Fabio Estevam, Saleem Abdulrasool
In-Reply-To: <4EEEDE94.3080804@googlemail.com>
On Mon, Dec 19, 2011 at 07:49:56AM +0100, Dirk Behme wrote:
> On 19.12.2011 04:49, Shawn Guo wrote:
> >On Sun, Dec 18, 2011 at 06:34:14PM +0100, Dirk Behme wrote:
> >>Factor out the uart save/restore functionality instead of
> >>having the same code several times in the driver.
> >>
> >>Signed-off-by: Dirk Behme<dirk.behme@gmail.com>
> >>CC: Saleem Abdulrasool<compnerd@compnerd.org>
> >>CC: Sascha Hauer<s.hauer@pengutronix.de>
> >>CC: Fabio Estevam<festevam@gmail.com>
> >>CC: Uwe Kleine-König<u.kleine-koenig@pengutronix.de>
> >>CC: linux-serial@vger.kernel.org
> >>---
> >> drivers/tty/serial/imx.c | 38 +++++++++++++++++++++++++++++++-------
> >> 1 files changed, 31 insertions(+), 7 deletions(-)
> >>
> >>diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> >>index 163fc90..6a01c2a 100644
> >>--- a/drivers/tty/serial/imx.c
> >>+++ b/drivers/tty/serial/imx.c
> >>@@ -260,6 +260,31 @@ static inline int is_imx21_uart(struct imx_port *sport)
> >> }
> >>
> >> /*
> >>+ * Save and restore functions for UCR1, UCR2 and UCR3 registers
> >>+ */
> >>+static void imx_console_mode(struct uart_port *port,
> >
> >Function name imx_console_mode seems not like a couple with
> >imx_console_restore. And I guess something like
> >imx_port_ucrs_save[restore] would be better?
> >
> >>+ unsigned int *ucr1,
> >>+ unsigned int *ucr2,
> >>+ unsigned int *ucr3)
> >
> >Can we define something like 'struct imx_port_ucrs' to contains these?
>
> Yes, we could have different function names above and use a struct.
>
> I implemented what Sascha asked for in
>
> http://www.spinics.net/lists/arm-kernel/msg144960.html
>
> though:
>
> -- Sascha wrote: --
> I'm thinking about:
>
> imx_console_mode(struct uart_port *port, u32 *ucr1, u32 *ucr2, u32 *ucr2);
> imx_console_restore(struct uart_port *port, u32 ucr1, u32 ucr2, u32 ucr3);
> -- Sascha end --
>
> It seems Shawn proposes
>
> imx_port_ucrs_save(struct uart_port *port, struct *imx_port_ucrs);
> imx_port_ucrs_restore(struct uart_port *port, struct *imx_port_ucrs);
>
> (?)
>
> Sascha, Shawn: Could you agree on what we should use?
I think save/restore are better names.
Maybe I thought about a function which saves the current values *and*
sets ucrx to other values. In that case imx_port_ucrs_save() would be
the wrong name.
>
> Once you agreed, I will send an update of both two patches.
+1 for save/restore
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] imx: Add save/restore functions for UART control regs
From: Shawn Guo @ 2011-12-19 7:20 UTC (permalink / raw)
To: Dirk Behme
Cc: Sascha Hauer, linux-arm-kernel, Dirk Behme, linux-serial,
Uwe Kleine-König, Fabio Estevam, Saleem Abdulrasool
In-Reply-To: <4EEEDE94.3080804@googlemail.com>
On Mon, Dec 19, 2011 at 07:49:56AM +0100, Dirk Behme wrote:
> On 19.12.2011 04:49, Shawn Guo wrote:
> >On Sun, Dec 18, 2011 at 06:34:14PM +0100, Dirk Behme wrote:
> >>Factor out the uart save/restore functionality instead of
> >>having the same code several times in the driver.
> >>
> >>Signed-off-by: Dirk Behme<dirk.behme@gmail.com>
> >>CC: Saleem Abdulrasool<compnerd@compnerd.org>
> >>CC: Sascha Hauer<s.hauer@pengutronix.de>
> >>CC: Fabio Estevam<festevam@gmail.com>
> >>CC: Uwe Kleine-König<u.kleine-koenig@pengutronix.de>
> >>CC: linux-serial@vger.kernel.org
> >>---
> >> drivers/tty/serial/imx.c | 38 +++++++++++++++++++++++++++++++-------
> >> 1 files changed, 31 insertions(+), 7 deletions(-)
> >>
> >>diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> >>index 163fc90..6a01c2a 100644
> >>--- a/drivers/tty/serial/imx.c
> >>+++ b/drivers/tty/serial/imx.c
> >>@@ -260,6 +260,31 @@ static inline int is_imx21_uart(struct imx_port *sport)
> >> }
> >>
> >> /*
> >>+ * Save and restore functions for UCR1, UCR2 and UCR3 registers
> >>+ */
> >>+static void imx_console_mode(struct uart_port *port,
> >
> >Function name imx_console_mode seems not like a couple with
> >imx_console_restore. And I guess something like
> >imx_port_ucrs_save[restore] would be better?
> >
> >>+ unsigned int *ucr1,
> >>+ unsigned int *ucr2,
> >>+ unsigned int *ucr3)
> >
> >Can we define something like 'struct imx_port_ucrs' to contains these?
>
> Yes, we could have different function names above and use a struct.
>
> I implemented what Sascha asked for in
>
> http://www.spinics.net/lists/arm-kernel/msg144960.html
>
> though:
>
> -- Sascha wrote: --
> I'm thinking about:
>
> imx_console_mode(struct uart_port *port, u32 *ucr1, u32 *ucr2, u32 *ucr2);
> imx_console_restore(struct uart_port *port, u32 ucr1, u32 ucr2, u32 ucr3);
> -- Sascha end --
>
> It seems Shawn proposes
>
> imx_port_ucrs_save(struct uart_port *port, struct *imx_port_ucrs);
> imx_port_ucrs_restore(struct uart_port *port, struct *imx_port_ucrs);
>
> (?)
>
> Sascha, Shawn: Could you agree on what we should use?
>
> Once you agreed, I will send an update of both two patches.
>
Please Cc Alan Cox <alan@linux.intel.com> for these patches. Though we
could possibly send them through arm-soc tree, we need to ask for his ack.
--
Regards,
Shawn
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] imx: Add save/restore functions for UART control regs
From: Dirk Behme @ 2011-12-19 6:49 UTC (permalink / raw)
To: Shawn Guo, Sascha Hauer
Cc: linux-arm-kernel, Dirk Behme, linux-serial, Uwe Kleine-König,
Fabio Estevam, Saleem Abdulrasool
In-Reply-To: <20111219034902.GC4962@S2100-06.ap.freescale.net>
On 19.12.2011 04:49, Shawn Guo wrote:
> On Sun, Dec 18, 2011 at 06:34:14PM +0100, Dirk Behme wrote:
>> Factor out the uart save/restore functionality instead of
>> having the same code several times in the driver.
>>
>> Signed-off-by: Dirk Behme<dirk.behme@gmail.com>
>> CC: Saleem Abdulrasool<compnerd@compnerd.org>
>> CC: Sascha Hauer<s.hauer@pengutronix.de>
>> CC: Fabio Estevam<festevam@gmail.com>
>> CC: Uwe Kleine-König<u.kleine-koenig@pengutronix.de>
>> CC: linux-serial@vger.kernel.org
>> ---
>> drivers/tty/serial/imx.c | 38 +++++++++++++++++++++++++++++++-------
>> 1 files changed, 31 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
>> index 163fc90..6a01c2a 100644
>> --- a/drivers/tty/serial/imx.c
>> +++ b/drivers/tty/serial/imx.c
>> @@ -260,6 +260,31 @@ static inline int is_imx21_uart(struct imx_port *sport)
>> }
>>
>> /*
>> + * Save and restore functions for UCR1, UCR2 and UCR3 registers
>> + */
>> +static void imx_console_mode(struct uart_port *port,
>
> Function name imx_console_mode seems not like a couple with
> imx_console_restore. And I guess something like
> imx_port_ucrs_save[restore] would be better?
>
>> + unsigned int *ucr1,
>> + unsigned int *ucr2,
>> + unsigned int *ucr3)
>
> Can we define something like 'struct imx_port_ucrs' to contains these?
Yes, we could have different function names above and use a struct.
I implemented what Sascha asked for in
http://www.spinics.net/lists/arm-kernel/msg144960.html
though:
-- Sascha wrote: --
I'm thinking about:
imx_console_mode(struct uart_port *port, u32 *ucr1, u32 *ucr2, u32 *ucr2);
imx_console_restore(struct uart_port *port, u32 ucr1, u32 ucr2, u32 ucr3);
-- Sascha end --
It seems Shawn proposes
imx_port_ucrs_save(struct uart_port *port, struct *imx_port_ucrs);
imx_port_ucrs_restore(struct uart_port *port, struct *imx_port_ucrs);
(?)
Sascha, Shawn: Could you agree on what we should use?
Once you agreed, I will send an update of both two patches.
Many thanks and best regards
Dirk
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/2 v2] imx: add polled io uart methods
From: Shawn Guo @ 2011-12-19 3:52 UTC (permalink / raw)
To: Dirk Behme
Cc: linux-arm-kernel, Sascha Hauer, Dirk Behme, linux-serial,
Uwe Kleine-König, Fabio Estevam, Saleem Abdulrasool
In-Reply-To: <1324229655-5538-2-git-send-email-dirk.behme@gmail.com>
On Sun, Dec 18, 2011 at 06:34:15PM +0100, Dirk Behme wrote:
> From: Saleem Abdulrasool <compnerd@compnerd.org>
>
> These methods are invoked if the iMX uart is used in conjuction with kgdb during
> early boot. In order to access the UART without the interrupts, the kernel uses
> the basic polling methods for IO with the device. With these methods
> implemented, it is now possible to enable kgdb during early boot over serial.
>
> Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org>
> Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
> CC: Sascha Hauer <s.hauer@pengutronix.de>
> CC: Fabio Estevam <festevam@gmail.com>
> CC: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> CC: linux-serial@vger.kernel.org
> ---
> Note: Changes in the v2 compared to Saleem's original version:
> * Remove volatile form status variable
> * Remove blank line
> * Factor out imx_console_mode/restore()
>
> drivers/tty/serial/imx.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 66 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 6a01c2a..cd81ac0 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -102,6 +102,7 @@
> #define UCR2_STPB (1<<6) /* Stop */
> #define UCR2_WS (1<<5) /* Word size */
> #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
> +#define UCR2_ATEN (1<<3) /* Aging Timer Enable */
> #define UCR2_TXEN (1<<2) /* Transmitter enabled */
> #define UCR2_RXEN (1<<1) /* Receiver enabled */
> #define UCR2_SRST (1<<0) /* SW reset */
> @@ -1104,6 +1105,66 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
> return ret;
> }
>
> +#if defined(CONFIG_CONSOLE_POLL)
> +static int imx_poll_get_char(struct uart_port *port)
> +{
> + unsigned int status, cr1, cr2, cr3;
> + unsigned char c;
> +
> + /* save control registers */
> + imx_console_mode(port, &cr1, &cr2, &cr3);
> +
> + /* disable interrupts */
> + writel(UCR1_UARTEN, port->membase + UCR1);
> + writel(cr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
> + port->membase + UCR2);
> + writel(cr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), port->membase + UCR3);
> +
> + /* poll */
> + do {
> + status = readl(port->membase + USR2);
> + } while (~status & USR2_RDR);
> +
> + /* read */
> + c = readl(port->membase + URXD0);
> +
> + /* restore control registers */
> + imx_console_restore(port, cr1, cr2, cr3);
> +
> + return c & 0xff;
The 'c' is defined an 'unsigned char'. Do we still need '& 0xff'?
> +}
> +
> +static void imx_poll_put_char(struct uart_port *port, unsigned char c)
> +{
> + unsigned int status, cr1, cr2, cr3;
> +
> + /* save control registers */
> + imx_console_mode(port, &cr1, &cr2, &cr3);
> +
> + /* disable interrupts */
> + writel(UCR1_UARTEN, port->membase + UCR1);
> + writel(cr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
> + port->membase + UCR2);
> + writel(cr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), port->membase + UCR3);
> +
> + /* drain */
> + do {
> + status = readl(port->membase + USR1);
> + } while (~status & USR1_TRDY);
> +
> + /* write */
> + writel(c, port->membase + URTX0);
> +
> + /* flush */
> + do {
> + status = readl(port->membase + USR2);
> + } while (~status & USR2_TXDC);
> +
> + /* restore control registers */
> + imx_console_restore(port, cr1, cr2, cr3);
> +}
> +#endif
> +
> static struct uart_ops imx_pops = {
> .tx_empty = imx_tx_empty,
> .set_mctrl = imx_set_mctrl,
> @@ -1121,6 +1182,11 @@ static struct uart_ops imx_pops = {
> .request_port = imx_request_port,
> .config_port = imx_config_port,
> .verify_port = imx_verify_port,
> +
Unnecessary blank line?
Regards,
Shawn
> +#if defined(CONFIG_CONSOLE_POLL)
> + .poll_get_char = imx_poll_get_char,
> + .poll_put_char = imx_poll_put_char,
> +#endif
> };
>
> static struct imx_port *imx_ports[UART_NR];
> --
> 1.7.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] imx: Add save/restore functions for UART control regs
From: Shawn Guo @ 2011-12-19 3:49 UTC (permalink / raw)
To: Dirk Behme
Cc: linux-arm-kernel, Sascha Hauer, Dirk Behme, linux-serial,
Uwe Kleine-König, Fabio Estevam, Saleem Abdulrasool
In-Reply-To: <1324229655-5538-1-git-send-email-dirk.behme@gmail.com>
On Sun, Dec 18, 2011 at 06:34:14PM +0100, Dirk Behme wrote:
> Factor out the uart save/restore functionality instead of
> having the same code several times in the driver.
>
> Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
> CC: Saleem Abdulrasool <compnerd@compnerd.org>
> CC: Sascha Hauer <s.hauer@pengutronix.de>
> CC: Fabio Estevam <festevam@gmail.com>
> CC: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> CC: linux-serial@vger.kernel.org
> ---
> drivers/tty/serial/imx.c | 38 +++++++++++++++++++++++++++++++-------
> 1 files changed, 31 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 163fc90..6a01c2a 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -260,6 +260,31 @@ static inline int is_imx21_uart(struct imx_port *sport)
> }
>
> /*
> + * Save and restore functions for UCR1, UCR2 and UCR3 registers
> + */
> +static void imx_console_mode(struct uart_port *port,
Function name imx_console_mode seems not like a couple with
imx_console_restore. And I guess something like
imx_port_ucrs_save[restore] would be better?
> + unsigned int *ucr1,
> + unsigned int *ucr2,
> + unsigned int *ucr3)
Can we define something like 'struct imx_port_ucrs' to contains these?
Regards,
Shawn
> +{
> + /* save control registers */
> + *ucr1 = readl(port->membase + UCR1);
> + *ucr2 = readl(port->membase + UCR2);
> + *ucr3 = readl(port->membase + UCR3);
> +}
> +
> +static void imx_console_restore(struct uart_port *port,
> + unsigned int ucr1,
> + unsigned int ucr2,
> + unsigned int ucr3)
> +{
> + /* restore control registers */
> + writel(ucr1, port->membase + UCR1);
> + writel(ucr2, port->membase + UCR2);
> + writel(ucr3, port->membase + UCR3);
> +}
> +
> +/*
> * Handle any change of modem status signal since we were last called.
> */
> static void imx_mctrl_check(struct imx_port *sport)
> @@ -1118,13 +1143,13 @@ static void
> imx_console_write(struct console *co, const char *s, unsigned int count)
> {
> struct imx_port *sport = imx_ports[co->index];
> - unsigned int old_ucr1, old_ucr2, ucr1;
> + unsigned int old_ucr1, old_ucr2, old_ucr3, ucr1;
>
> /*
> - * First, save UCR1/2 and then disable interrupts
> + * First, save UCR1/2/3 and then disable interrupts
> */
> - ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
> - old_ucr2 = readl(sport->port.membase + UCR2);
> + imx_console_mode(&sport->port, &old_ucr1, &old_ucr2, &old_ucr3);
> + ucr1 = old_ucr1;
>
> if (is_imx1_uart(sport))
> ucr1 |= IMX1_UCR1_UARTCLKEN;
> @@ -1139,12 +1164,11 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
>
> /*
> * Finally, wait for transmitter to become empty
> - * and restore UCR1/2
> + * and restore UCR1/2/3
> */
> while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
>
> - writel(old_ucr1, sport->port.membase + UCR1);
> - writel(old_ucr2, sport->port.membase + UCR2);
> + imx_console_restore(&sport->port, old_ucr1, old_ucr2, old_ucr3);
> }
>
> /*
> --
> 1.7.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 2/2 v2] imx: add polled io uart methods
From: Dirk Behme @ 2011-12-18 17:34 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Saleem Abdulrasool, Dirk Behme, Sascha Hauer, Fabio Estevam,
Uwe Kleine-König, linux-serial
In-Reply-To: <1324229655-5538-1-git-send-email-dirk.behme@gmail.com>
From: Saleem Abdulrasool <compnerd@compnerd.org>
These methods are invoked if the iMX uart is used in conjuction with kgdb during
early boot. In order to access the UART without the interrupts, the kernel uses
the basic polling methods for IO with the device. With these methods
implemented, it is now possible to enable kgdb during early boot over serial.
Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org>
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Fabio Estevam <festevam@gmail.com>
CC: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
CC: linux-serial@vger.kernel.org
---
Note: Changes in the v2 compared to Saleem's original version:
* Remove volatile form status variable
* Remove blank line
* Factor out imx_console_mode/restore()
drivers/tty/serial/imx.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 6a01c2a..cd81ac0 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -102,6 +102,7 @@
#define UCR2_STPB (1<<6) /* Stop */
#define UCR2_WS (1<<5) /* Word size */
#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
+#define UCR2_ATEN (1<<3) /* Aging Timer Enable */
#define UCR2_TXEN (1<<2) /* Transmitter enabled */
#define UCR2_RXEN (1<<1) /* Receiver enabled */
#define UCR2_SRST (1<<0) /* SW reset */
@@ -1104,6 +1105,66 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
return ret;
}
+#if defined(CONFIG_CONSOLE_POLL)
+static int imx_poll_get_char(struct uart_port *port)
+{
+ unsigned int status, cr1, cr2, cr3;
+ unsigned char c;
+
+ /* save control registers */
+ imx_console_mode(port, &cr1, &cr2, &cr3);
+
+ /* disable interrupts */
+ writel(UCR1_UARTEN, port->membase + UCR1);
+ writel(cr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
+ port->membase + UCR2);
+ writel(cr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), port->membase + UCR3);
+
+ /* poll */
+ do {
+ status = readl(port->membase + USR2);
+ } while (~status & USR2_RDR);
+
+ /* read */
+ c = readl(port->membase + URXD0);
+
+ /* restore control registers */
+ imx_console_restore(port, cr1, cr2, cr3);
+
+ return c & 0xff;
+}
+
+static void imx_poll_put_char(struct uart_port *port, unsigned char c)
+{
+ unsigned int status, cr1, cr2, cr3;
+
+ /* save control registers */
+ imx_console_mode(port, &cr1, &cr2, &cr3);
+
+ /* disable interrupts */
+ writel(UCR1_UARTEN, port->membase + UCR1);
+ writel(cr2 & ~(UCR2_ATEN | UCR2_RTSEN | UCR2_ESCI),
+ port->membase + UCR2);
+ writel(cr3 & ~(UCR3_DCD | UCR3_RI | UCR3_DTREN), port->membase + UCR3);
+
+ /* drain */
+ do {
+ status = readl(port->membase + USR1);
+ } while (~status & USR1_TRDY);
+
+ /* write */
+ writel(c, port->membase + URTX0);
+
+ /* flush */
+ do {
+ status = readl(port->membase + USR2);
+ } while (~status & USR2_TXDC);
+
+ /* restore control registers */
+ imx_console_restore(port, cr1, cr2, cr3);
+}
+#endif
+
static struct uart_ops imx_pops = {
.tx_empty = imx_tx_empty,
.set_mctrl = imx_set_mctrl,
@@ -1121,6 +1182,11 @@ static struct uart_ops imx_pops = {
.request_port = imx_request_port,
.config_port = imx_config_port,
.verify_port = imx_verify_port,
+
+#if defined(CONFIG_CONSOLE_POLL)
+ .poll_get_char = imx_poll_get_char,
+ .poll_put_char = imx_poll_put_char,
+#endif
};
static struct imx_port *imx_ports[UART_NR];
--
1.7.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/2] imx: Add save/restore functions for UART control regs
From: Dirk Behme @ 2011-12-18 17:34 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Dirk Behme, Saleem Abdulrasool, Sascha Hauer, Fabio Estevam,
Uwe Kleine-König, linux-serial
Factor out the uart save/restore functionality instead of
having the same code several times in the driver.
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
CC: Saleem Abdulrasool <compnerd@compnerd.org>
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Fabio Estevam <festevam@gmail.com>
CC: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
CC: linux-serial@vger.kernel.org
---
drivers/tty/serial/imx.c | 38 +++++++++++++++++++++++++++++++-------
1 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 163fc90..6a01c2a 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -260,6 +260,31 @@ static inline int is_imx21_uart(struct imx_port *sport)
}
/*
+ * Save and restore functions for UCR1, UCR2 and UCR3 registers
+ */
+static void imx_console_mode(struct uart_port *port,
+ unsigned int *ucr1,
+ unsigned int *ucr2,
+ unsigned int *ucr3)
+{
+ /* save control registers */
+ *ucr1 = readl(port->membase + UCR1);
+ *ucr2 = readl(port->membase + UCR2);
+ *ucr3 = readl(port->membase + UCR3);
+}
+
+static void imx_console_restore(struct uart_port *port,
+ unsigned int ucr1,
+ unsigned int ucr2,
+ unsigned int ucr3)
+{
+ /* restore control registers */
+ writel(ucr1, port->membase + UCR1);
+ writel(ucr2, port->membase + UCR2);
+ writel(ucr3, port->membase + UCR3);
+}
+
+/*
* Handle any change of modem status signal since we were last called.
*/
static void imx_mctrl_check(struct imx_port *sport)
@@ -1118,13 +1143,13 @@ static void
imx_console_write(struct console *co, const char *s, unsigned int count)
{
struct imx_port *sport = imx_ports[co->index];
- unsigned int old_ucr1, old_ucr2, ucr1;
+ unsigned int old_ucr1, old_ucr2, old_ucr3, ucr1;
/*
- * First, save UCR1/2 and then disable interrupts
+ * First, save UCR1/2/3 and then disable interrupts
*/
- ucr1 = old_ucr1 = readl(sport->port.membase + UCR1);
- old_ucr2 = readl(sport->port.membase + UCR2);
+ imx_console_mode(&sport->port, &old_ucr1, &old_ucr2, &old_ucr3);
+ ucr1 = old_ucr1;
if (is_imx1_uart(sport))
ucr1 |= IMX1_UCR1_UARTCLKEN;
@@ -1139,12 +1164,11 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
/*
* Finally, wait for transmitter to become empty
- * and restore UCR1/2
+ * and restore UCR1/2/3
*/
while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
- writel(old_ucr1, sport->port.membase + UCR1);
- writel(old_ucr2, sport->port.membase + UCR2);
+ imx_console_restore(&sport->port, old_ucr1, old_ucr2, old_ucr3);
}
/*
--
1.7.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v3 0/4] OMAP serial device tree support
From: Tony Lindgren @ 2011-12-16 22:17 UTC (permalink / raw)
To: Greg KH
Cc: Alan Cox, Kevin Hilman, Rajendra Nayak, linux-serial, linux-omap,
devicetree-discuss, govindraj.raja, b-cousson, linux-arm-kernel,
linaro-dev, patches, robherring2
In-Reply-To: <20111214182710.GC8039@kroah.com>
* Greg KH <greg@kroah.com> [111214 10:27]:
> On Wed, Dec 14, 2011 at 05:18:43PM +0000, Alan Cox wrote:
> > On Wed, 14 Dec 2011 07:20:13 -0800
> > Kevin Hilman <khilman@ti.com> wrote:
> >
> > > Greg, Alan,
> > >
> > > Rajendra Nayak <rnayak@ti.com> writes:
> > >
> > > > v3 is rebased on top of the latest serial runtime
> > > > patches[1] and boot tested with/without DT on OMAP4
> > > > SDP and OMAP4 Panda boards.
> > >
> > > With your ack on the drivers/tty/* stuff, I can queue this via the
> > > OMAP tree on top of the runtime PM conversion that it depends on.
> >
> > Go for it
>
> Fine with me as well.
For the record, I'll apply these directly into the omap uart
branch as Kevin is on vacation.
Regards,
Tony
^ permalink raw reply
* Re: [PATCH v3 0/4] OMAP serial device tree support
From: Tony Lindgren @ 2011-12-16 22:09 UTC (permalink / raw)
To: Rob Herring
Cc: Rajendra Nayak, linux-serial, linux-omap, devicetree-discuss,
khilman, govindraj.raja, b-cousson, linux-arm-kernel, linaro-dev,
patches
In-Reply-To: <4EEBBFDD.1010509@gmail.com>
* Rob Herring <robherring2@gmail.com> [111216 13:30]:
> Tony,
>
> On 12/16/2011 03:57 PM, Tony Lindgren wrote:
> > Rob,
> >
> > * Rob Herring <robherring2@gmail.com> [111214 05:16]:
> >> On 12/14/2011 05:55 AM, Rajendra Nayak wrote:
> >>> v3 is rebased on top of the latest serial runtime
> >>> patches[1] and boot tested with/without DT on OMAP4
> >>> SDP and OMAP4 Panda boards.
> >>>
> >>> Patches can be found here..
> >>> git://gitorious.org/omap-pm/linux.git for-dt/serial
> >>>
> >>> I also had to pull in a fix[2] for DT testing (already in linux-omap
> >>> master) which was missing as the serial runtime branch[1]
> >>> was based on an older master commit.
> >>>
> >>> Changes in v3:
> >>> -1- Rebased on latest serial runtime patches
> >>> -2- Minor typr fixes
> >>>
> >>> Changes in v2:
> >>> -1- Got rid of binding to define which uart is console
> >>> -2- Added checks to default clock speed to 48Mhz
> >>> -3- Added compatible for each OMAP family
> >>> -4- Used of_alias_get_id to populate port.line
> >>>
> >>> [1] git://gitorious.org/runtime_3-0/runtime_3-0.git for_3_3/lo_rc4_uartruntime
> >>> [2] http://www.spinics.net/lists/arm-kernel/msg150751.html
> >>>
> >>> Rajendra Nayak (4):
> >>> omap-serial: Get rid of all pdev->id usage
> >>> omap-serial: Use default clock speed (48Mhz) if not specified
> >>> omap-serial: Add minimal device tree support
> >>> ARM: omap: pass minimal SoC/board data for UART from dt
> >>>
> >>> .../devicetree/bindings/serial/omap_serial.txt | 10 +++
> >>> arch/arm/boot/dts/omap3.dtsi | 31 ++++++++
> >>> arch/arm/boot/dts/omap4.dtsi | 28 +++++++
> >>> arch/arm/mach-omap2/board-generic.c | 1 -
> >>> drivers/tty/serial/omap-serial.c | 80 +++++++++++++++----
> >>> 5 files changed, 132 insertions(+), 18 deletions(-)
> >>> create mode 100644 Documentation/devicetree/bindings/serial/omap_serial.txt
> >>
> >> Looks good. For the series:
> >>
> >> Reviewed-by: Rob Herring <rob.herring@calxeda.com>
> >
> > Care to check if your Reviewed-by can also be applied
> > to the additional patch "[PATCH] arm/dts: Add minimal device
> > tree support for omap2420 and omap2430" that's needed
> > to keep serial port working for omap2 with this series?
>
> It looks fine.
OK thanks.
Tony
^ permalink raw reply
* Re: [PATCH v3 0/4] OMAP serial device tree support
From: Rob Herring @ 2011-12-16 22:02 UTC (permalink / raw)
To: Tony Lindgren
Cc: Rajendra Nayak, linux-serial, linux-omap, devicetree-discuss,
khilman, govindraj.raja, b-cousson, linux-arm-kernel, linaro-dev,
patches
In-Reply-To: <20111216215731.GQ32251@atomide.com>
Tony,
On 12/16/2011 03:57 PM, Tony Lindgren wrote:
> Rob,
>
> * Rob Herring <robherring2@gmail.com> [111214 05:16]:
>> On 12/14/2011 05:55 AM, Rajendra Nayak wrote:
>>> v3 is rebased on top of the latest serial runtime
>>> patches[1] and boot tested with/without DT on OMAP4
>>> SDP and OMAP4 Panda boards.
>>>
>>> Patches can be found here..
>>> git://gitorious.org/omap-pm/linux.git for-dt/serial
>>>
>>> I also had to pull in a fix[2] for DT testing (already in linux-omap
>>> master) which was missing as the serial runtime branch[1]
>>> was based on an older master commit.
>>>
>>> Changes in v3:
>>> -1- Rebased on latest serial runtime patches
>>> -2- Minor typr fixes
>>>
>>> Changes in v2:
>>> -1- Got rid of binding to define which uart is console
>>> -2- Added checks to default clock speed to 48Mhz
>>> -3- Added compatible for each OMAP family
>>> -4- Used of_alias_get_id to populate port.line
>>>
>>> [1] git://gitorious.org/runtime_3-0/runtime_3-0.git for_3_3/lo_rc4_uartruntime
>>> [2] http://www.spinics.net/lists/arm-kernel/msg150751.html
>>>
>>> Rajendra Nayak (4):
>>> omap-serial: Get rid of all pdev->id usage
>>> omap-serial: Use default clock speed (48Mhz) if not specified
>>> omap-serial: Add minimal device tree support
>>> ARM: omap: pass minimal SoC/board data for UART from dt
>>>
>>> .../devicetree/bindings/serial/omap_serial.txt | 10 +++
>>> arch/arm/boot/dts/omap3.dtsi | 31 ++++++++
>>> arch/arm/boot/dts/omap4.dtsi | 28 +++++++
>>> arch/arm/mach-omap2/board-generic.c | 1 -
>>> drivers/tty/serial/omap-serial.c | 80 +++++++++++++++----
>>> 5 files changed, 132 insertions(+), 18 deletions(-)
>>> create mode 100644 Documentation/devicetree/bindings/serial/omap_serial.txt
>>
>> Looks good. For the series:
>>
>> Reviewed-by: Rob Herring <rob.herring@calxeda.com>
>
> Care to check if your Reviewed-by can also be applied
> to the additional patch "[PATCH] arm/dts: Add minimal device
> tree support for omap2420 and omap2430" that's needed
> to keep serial port working for omap2 with this series?
It looks fine.
Rob
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox