* [PATCH 0/2] Update uart irq handling for s3c64xx and later SoC's
@ 2011-08-10 10:21 Thomas Abraham
2011-08-10 10:21 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler " Thomas Abraham
2011-08-13 11:26 ` [PATCH 0/2] Update uart irq handling " Tomasz Figa
0 siblings, 2 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-08-10 10:21 UTC (permalink / raw)
To: linux-serial
Cc: alan, linux-arm-kernel, linux-samsung-soc, kgene.kim,
grant.likely, ben-linux
s3c64xx and later SoC's include the uart interrupt mask and pending registers
in the uart controller, unlike their s3c24xx predecessor. This allows the
uart irq handling to be moved from the platform code to the driver. This
patchset does this change and removes all the macros that will not be
required with this update.
Thomas Abraham (2):
serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's
ARM: SAMSUNG: Remove uart irq handling from plaform code
arch/arm/Kconfig | 1 -
arch/arm/mach-s3c64xx/dev-uart.c | 60 ++-----------
arch/arm/mach-s3c64xx/include/mach/irqs.h | 30 ------
arch/arm/mach-s3c64xx/irq.c | 25 -----
arch/arm/plat-s5p/Kconfig | 1 -
arch/arm/plat-s5p/dev-uart.c | 84 +++---------------
arch/arm/plat-s5p/include/plat/irqs.h | 35 -------
arch/arm/plat-s5p/irq.c | 34 -------
arch/arm/plat-samsung/Kconfig | 5 -
arch/arm/plat-samsung/Makefile | 1 -
arch/arm/plat-samsung/include/plat/regs-serial.h | 5 +
arch/arm/plat-samsung/irq-uart.c | 96 -------------------
drivers/tty/serial/samsung.c | 107 +++++++++++++++++++---
drivers/tty/serial/samsung.h | 1 +
14 files changed, 121 insertions(+), 364 deletions(-)
delete mode 100644 arch/arm/plat-samsung/irq-uart.c
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's
2011-08-10 10:21 [PATCH 0/2] Update uart irq handling for s3c64xx and later SoC's Thomas Abraham
@ 2011-08-10 10:21 ` Thomas Abraham
2011-08-10 10:21 ` [PATCH 2/2] ARM: SAMSUNG: Remove uart irq handling from plaform code Thomas Abraham
2011-08-10 11:55 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's Alan Cox
2011-08-13 11:26 ` [PATCH 0/2] Update uart irq handling " Tomasz Figa
1 sibling, 2 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-08-10 10:21 UTC (permalink / raw)
To: linux-serial
Cc: alan, linux-arm-kernel, linux-samsung-soc, kgene.kim,
grant.likely, ben-linux
s3c64xx and later SoC's include the interrupt mask and pending registers
in the uart controller, unlike the s3c24xx SoC's which have these registers
in the interrupt controller. When the mask and pending registers are part
of the uart controller, a unified interrupt handler can handle the tx/rx
interrupt. With this, the static reservation of interrupt numbers for the
uart tx/rx/err interrupts in the linux irq space is not required and
simplifies adding device tree support.
Suggested-by: Grant Likely <grant.likely@secretlab.ca>
CC: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
drivers/tty/serial/samsung.c | 107 +++++++++++++++++++++++++++++++++++++-----
drivers/tty/serial/samsung.h | 1 +
2 files changed, 96 insertions(+), 12 deletions(-)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index afc6294..9b84654 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -83,6 +83,16 @@ static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
}
+/*
+ * s3c64xx and later SoC's include the interrupt mask and status registers in
+ * the controller itself, unlike the s3c24xx SoC's which have these registers
+ * in the interrupt controller. Check if the port type is s3c64xx or higher.
+ */
+static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
+{
+ return to_ourport(port)->info->type == PORT_S3C6400;
+}
+
static void s3c24xx_serial_rx_enable(struct uart_port *port)
{
unsigned long flags;
@@ -126,7 +136,11 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (tx_enabled(port)) {
- disable_irq_nosync(ourport->tx_irq);
+ if (s3c24xx_serial_has_interrupt_mask(port))
+ __set_bit(S3C64XX_UINTM_TXD,
+ portaddrl(port, S3C64XX_UINTM));
+ else
+ disable_irq_nosync(ourport->tx_irq);
tx_enabled(port) = 0;
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_enable(port);
@@ -141,19 +155,26 @@ static void s3c24xx_serial_start_tx(struct uart_port *port)
if (port->flags & UPF_CONS_FLOW)
s3c24xx_serial_rx_disable(port);
- enable_irq(ourport->tx_irq);
+ if (s3c24xx_serial_has_interrupt_mask(port))
+ __clear_bit(S3C64XX_UINTM_TXD,
+ portaddrl(port, S3C64XX_UINTM));
+ else
+ enable_irq(ourport->tx_irq);
tx_enabled(port) = 1;
}
}
-
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (rx_enabled(port)) {
dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
- disable_irq_nosync(ourport->rx_irq);
+ if (s3c24xx_serial_has_interrupt_mask(port))
+ __set_bit(S3C64XX_UINTM_RXD,
+ portaddrl(port, S3C64XX_UINTM));
+ else
+ disable_irq_nosync(ourport->rx_irq);
rx_enabled(port) = 0;
}
}
@@ -320,6 +341,28 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
return IRQ_HANDLED;
}
+/* interrupt handler for s3c64xx and later SoC's.*/
+static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
+{
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+ unsigned int pend = rd_regl(port, S3C64XX_UINTP);
+ unsigned long flags;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (pend & S3C64XX_UINTM_RXD_MSK) {
+ ret = s3c24xx_serial_rx_chars(irq, id);
+ wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
+ }
+ if (pend & S3C64XX_UINTM_TXD_MSK) {
+ ret = s3c24xx_serial_tx_chars(irq, id);
+ wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+ return ret;
+}
+
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
@@ -377,18 +420,25 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (ourport->tx_claimed) {
- free_irq(ourport->tx_irq, ourport);
+ if (!s3c24xx_serial_has_interrupt_mask(port))
+ free_irq(ourport->tx_irq, ourport);
tx_enabled(port) = 0;
ourport->tx_claimed = 0;
}
if (ourport->rx_claimed) {
- free_irq(ourport->rx_irq, ourport);
+ if (!s3c24xx_serial_has_interrupt_mask(port))
+ free_irq(ourport->rx_irq, ourport);
ourport->rx_claimed = 0;
rx_enabled(port) = 0;
}
-}
+ /* Clear pending interrupts and mask all interrupts */
+ if (s3c24xx_serial_has_interrupt_mask(port)) {
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+ }
+}
static int s3c24xx_serial_startup(struct uart_port *port)
{
@@ -436,6 +486,33 @@ static int s3c24xx_serial_startup(struct uart_port *port)
return ret;
}
+static int s3c64xx_serial_startup(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ int ret;
+
+ dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n",
+ port->mapbase, port->membase);
+
+ ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
+ s3c24xx_serial_portname(port), ourport);
+ if (ret) {
+ printk(KERN_ERR "cannot get irq %d\n", port->irq);
+ return ret;
+ }
+
+ /* For compatibility with s3c24xx Soc's */
+ rx_enabled(port) = 1;
+ ourport->rx_claimed = 1;
+ tx_enabled(port) = 0;
+ ourport->tx_claimed = 1;
+
+ /* Enable Rx Interrupt */
+ __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
+ dbg("s3c64xx_serial_startup ok\n");
+ return ret;
+}
+
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -879,7 +956,6 @@ static struct uart_ops s3c24xx_serial_ops = {
.verify_port = s3c24xx_serial_verify_port,
};
-
static struct uart_driver s3c24xx_uart_drv = {
.owner = THIS_MODULE,
.driver_name = "s3c2410_serial",
@@ -895,7 +971,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX0,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
@@ -907,7 +982,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
.iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX1,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
@@ -921,7 +995,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
.iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX2,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
@@ -935,7 +1008,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
- .irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
@@ -1077,6 +1149,10 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
port->dev = &platdev->dev;
ourport->info = info;
+ /* Startup sequence is different for s3c64xx and higher SoC's */
+ if (s3c24xx_serial_has_interrupt_mask(port))
+ s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
+
/* copy the info in from provided structure */
ourport->port.fifosize = info->fifosize;
@@ -1116,6 +1192,13 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->clk = clk_get(&platdev->dev, "uart");
+ /* Keep all interrupts masked and cleared */
+ if (s3c24xx_serial_has_interrupt_mask(port)) {
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+ wr_regl(port, S3C64XX_UINTSP, 0xf);
+ }
+
dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n",
port->mapbase, port->membase, port->irq,
ourport->rx_irq, ourport->tx_irq, port->uartclk);
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index a69d9a5..8e87b78 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -61,6 +61,7 @@ struct s3c24xx_uart_port {
/* register access controls */
#define portaddr(port, reg) ((port)->membase + (reg))
+#define portaddrl(port, reg) ((unsigned long *)((port)->membase + (reg)))
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] ARM: SAMSUNG: Remove uart irq handling from plaform code
2011-08-10 10:21 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler " Thomas Abraham
@ 2011-08-10 10:21 ` Thomas Abraham
2011-08-10 11:55 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's Alan Cox
1 sibling, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-08-10 10:21 UTC (permalink / raw)
To: linux-serial
Cc: alan, linux-arm-kernel, linux-samsung-soc, kgene.kim,
grant.likely, ben-linux
With uart tx/rx/err interrupt handling moved into the driver for s3c64xx
and later SoC's, the uart interrupt handling in plaform code can be removed.
The uart device irq resources is reduced to one and the related unused
macros are removed.
Suggested-by: Grant Likely <grant.likely@secretlab.ca>
CC: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
arch/arm/Kconfig | 1 -
arch/arm/mach-s3c64xx/dev-uart.c | 60 ++------------
arch/arm/mach-s3c64xx/include/mach/irqs.h | 30 -------
arch/arm/mach-s3c64xx/irq.c | 25 ------
arch/arm/plat-s5p/Kconfig | 1 -
arch/arm/plat-s5p/dev-uart.c | 84 +++----------------
arch/arm/plat-s5p/include/plat/irqs.h | 35 --------
arch/arm/plat-s5p/irq.c | 34 --------
arch/arm/plat-samsung/Kconfig | 5 -
arch/arm/plat-samsung/Makefile | 1 -
arch/arm/plat-samsung/include/plat/regs-serial.h | 5 +
arch/arm/plat-samsung/irq-uart.c | 96 ----------------------
12 files changed, 25 insertions(+), 352 deletions(-)
delete mode 100644 arch/arm/plat-samsung/irq-uart.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2c71a8f..94228f7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -723,7 +723,6 @@ config ARCH_S3C64XX
select ARCH_REQUIRE_GPIOLIB
select SAMSUNG_CLKSRC
select SAMSUNG_IRQ_VIC_TIMER
- select SAMSUNG_IRQ_UART
select S3C_GPIO_TRACK
select S3C_GPIO_PULL_UPDOWN
select S3C_GPIO_CFG_S3C24XX
diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c
index f797f74..c681b99 100644
--- a/arch/arm/mach-s3c64xx/dev-uart.c
+++ b/arch/arm/mach-s3c64xx/dev-uart.c
@@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX0,
- .end = IRQ_S3CUART_RX0,
+ .start = IRQ_UART0,
+ .end = IRQ_UART0,
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = IRQ_S3CUART_TX0,
- .end = IRQ_S3CUART_TX0,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR0,
- .end = IRQ_S3CUART_ERR0,
- .flags = IORESOURCE_IRQ,
- }
};
static struct resource s3c64xx_uart1_resource[] = {
@@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX1,
- .end = IRQ_S3CUART_RX1,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX1,
- .end = IRQ_S3CUART_TX1,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR1,
- .end = IRQ_S3CUART_ERR1,
+ .start = IRQ_UART1,
+ .end = IRQ_UART1,
.flags = IORESOURCE_IRQ,
},
};
@@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX2,
- .end = IRQ_S3CUART_RX2,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX2,
- .end = IRQ_S3CUART_TX2,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR2,
- .end = IRQ_S3CUART_ERR2,
+ .start = IRQ_UART2,
+ .end = IRQ_UART2,
.flags = IORESOURCE_IRQ,
},
};
@@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S3CUART_RX3,
- .end = IRQ_S3CUART_RX3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S3CUART_TX3,
- .end = IRQ_S3CUART_TX3,
- .flags = IORESOURCE_IRQ,
-
- },
- [3] = {
- .start = IRQ_S3CUART_ERR3,
- .end = IRQ_S3CUART_ERR3,
+ .start = IRQ_UART3,
+ .end = IRQ_UART3,
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
index c026f67..443f85b 100644
--- a/arch/arm/mach-s3c64xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -27,36 +27,6 @@
#define IRQ_VIC0_BASE S3C_IRQ(0)
#define IRQ_VIC1_BASE S3C_IRQ(32)
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0 (16)
-#define IRQ_S3CUART_BASE1 (20)
-#define IRQ_S3CUART_BASE2 (24)
-#define IRQ_S3CUART_BASE3 (28)
-
-#define UART_IRQ_RXD (0)
-#define UART_IRQ_ERR (1)
-#define UART_IRQ_TXD (2)
-#define UART_IRQ_MODEM (3)
-
-#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
/* VIC based IRQs */
#define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x))
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c
index 75d9a0e..b07357e 100644
--- a/arch/arm/mach-s3c64xx/irq.c
+++ b/arch/arm/mach-s3c64xx/irq.c
@@ -25,29 +25,6 @@
#include <plat/irq-uart.h>
#include <plat/cpu.h>
-static struct s3c_uart_irq uart_irqs[] = {
- [0] = {
- .regs = S3C_VA_UART0,
- .base_irq = IRQ_S3CUART_BASE0,
- .parent_irq = IRQ_UART0,
- },
- [1] = {
- .regs = S3C_VA_UART1,
- .base_irq = IRQ_S3CUART_BASE1,
- .parent_irq = IRQ_UART1,
- },
- [2] = {
- .regs = S3C_VA_UART2,
- .base_irq = IRQ_S3CUART_BASE2,
- .parent_irq = IRQ_UART2,
- },
- [3] = {
- .regs = S3C_VA_UART3,
- .base_irq = IRQ_S3CUART_BASE3,
- .parent_irq = IRQ_UART3,
- },
-};
-
/* setup the sources the vic should advertise resume for, even though it
* is not doing the wake (set_irq_wake needs to be valid) */
#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
@@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
/* add the timer sub-irqs */
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
- s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 9843c95..9a197e5 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -22,7 +22,6 @@ config PLAT_S5P
select PLAT_SAMSUNG
select SAMSUNG_CLKSRC
select SAMSUNG_IRQ_VIC_TIMER
- select SAMSUNG_IRQ_UART
help
Base platform code for Samsung's S5P series SoC.
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c
index afaf87f..c9308db 100644
--- a/arch/arm/plat-s5p/dev-uart.c
+++ b/arch/arm/plat-s5p/dev-uart.c
@@ -32,20 +32,10 @@ static struct resource s5p_uart0_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX0,
- .end = IRQ_S5P_UART_RX0,
+ .start = IRQ_UART0,
+ .end = IRQ_UART0,
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = IRQ_S5P_UART_TX0,
- .end = IRQ_S5P_UART_TX0,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR0,
- .end = IRQ_S5P_UART_ERR0,
- .flags = IORESOURCE_IRQ,
- }
};
static struct resource s5p_uart1_resource[] = {
@@ -55,18 +45,8 @@ static struct resource s5p_uart1_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX1,
- .end = IRQ_S5P_UART_RX1,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX1,
- .end = IRQ_S5P_UART_TX1,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR1,
- .end = IRQ_S5P_UART_ERR1,
+ .start = IRQ_UART1,
+ .end = IRQ_UART1,
.flags = IORESOURCE_IRQ,
},
};
@@ -78,18 +58,8 @@ static struct resource s5p_uart2_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX2,
- .end = IRQ_S5P_UART_RX2,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX2,
- .end = IRQ_S5P_UART_TX2,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR2,
- .end = IRQ_S5P_UART_ERR2,
+ .start = IRQ_UART2,
+ .end = IRQ_UART2,
.flags = IORESOURCE_IRQ,
},
};
@@ -102,18 +72,8 @@ static struct resource s5p_uart3_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX3,
- .end = IRQ_S5P_UART_RX3,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX3,
- .end = IRQ_S5P_UART_TX3,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR3,
- .end = IRQ_S5P_UART_ERR3,
+ .start = IRQ_UART3,
+ .end = IRQ_UART3,
.flags = IORESOURCE_IRQ,
},
#endif
@@ -127,18 +87,8 @@ static struct resource s5p_uart4_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX4,
- .end = IRQ_S5P_UART_RX4,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX4,
- .end = IRQ_S5P_UART_TX4,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR4,
- .end = IRQ_S5P_UART_ERR4,
+ .start = IRQ_UART4,
+ .end = IRQ_UART4,
.flags = IORESOURCE_IRQ,
},
#endif
@@ -152,18 +102,8 @@ static struct resource s5p_uart5_resource[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_S5P_UART_RX5,
- .end = IRQ_S5P_UART_RX5,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_S5P_UART_TX5,
- .end = IRQ_S5P_UART_TX5,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = IRQ_S5P_UART_ERR5,
- .end = IRQ_S5P_UART_ERR5,
+ .start = IRQ_UART5,
+ .end = IRQ_UART5,
.flags = IORESOURCE_IRQ,
},
#endif
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h
index ba9121c..144dbfc 100644
--- a/arch/arm/plat-s5p/include/plat/irqs.h
+++ b/arch/arm/plat-s5p/include/plat/irqs.h
@@ -37,41 +37,6 @@
#define IRQ_VIC1_BASE S5P_VIC1_BASE
#define IRQ_VIC2_BASE S5P_VIC2_BASE
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S5P_UART_BASE0 (16)
-#define IRQ_S5P_UART_BASE1 (20)
-#define IRQ_S5P_UART_BASE2 (24)
-#define IRQ_S5P_UART_BASE3 (28)
-
-#define UART_IRQ_RXD (0)
-#define UART_IRQ_ERR (1)
-#define UART_IRQ_TXD (2)
-
-#define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0
-#define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1
-#define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2
-#define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3
-
/* VIC based IRQs */
#define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x))
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
index a97c089..afdaa10 100644
--- a/arch/arm/plat-s5p/irq.c
+++ b/arch/arm/plat-s5p/irq.c
@@ -17,42 +17,10 @@
#include <asm/hardware/vic.h>
-#include <linux/serial_core.h>
#include <mach/map.h>
#include <plat/regs-timer.h>
-#include <plat/regs-serial.h>
#include <plat/cpu.h>
#include <plat/irq-vic-timer.h>
-#include <plat/irq-uart.h>
-
-/*
- * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static struct s3c_uart_irq uart_irqs[] = {
- [0] = {
- .regs = S5P_VA_UART0,
- .base_irq = IRQ_S5P_UART_BASE0,
- .parent_irq = IRQ_UART0,
- },
- [1] = {
- .regs = S5P_VA_UART1,
- .base_irq = IRQ_S5P_UART_BASE1,
- .parent_irq = IRQ_UART1,
- },
- [2] = {
- .regs = S5P_VA_UART2,
- .base_irq = IRQ_S5P_UART_BASE2,
- .parent_irq = IRQ_UART2,
- },
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
- [3] = {
- .regs = S5P_VA_UART3,
- .base_irq = IRQ_S5P_UART_BASE3,
- .parent_irq = IRQ_UART3,
- },
-#endif
-};
void __init s5p_init_irq(u32 *vic, u32 num_vic)
{
@@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
#endif
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
-
- s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index b3e1065..dffa37b 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER
help
Internal configuration to build the VIC timer interrupt code.
-config SAMSUNG_IRQ_UART
- bool
- help
- Internal configuration to build the IRQ UART demux code.
-
# options for gpio configuration support
config SAMSUNG_GPIOLIB_4BIT
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 853764b..1105922 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -21,7 +21,6 @@ obj-y += dev-asocdma.o
obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
-obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
# ADC
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index bac36fa..7207348 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -186,6 +186,11 @@
#define S3C64XX_UINTSP 0x34
#define S3C64XX_UINTM 0x38
+#define S3C64XX_UINTM_RXD (0)
+#define S3C64XX_UINTM_TXD (2)
+#define S3C64XX_UINTM_RXD_MSK (1 << S3C64XX_UINTM_RXD)
+#define S3C64XX_UINTM_TXD_MSK (1 << S3C64XX_UINTM_TXD)
+
/* Following are specific to S5PV210 */
#define S5PV210_UCON_CLKMASK (1<<10)
#define S5PV210_UCON_PCLK (0<<10)
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c
deleted file mode 100644
index 3014c72..0000000
--- a/arch/arm/plat-samsung/irq-uart.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* arch/arm/plat-samsung/irq-uart.c
- * originally part of arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * Samsung- UART Interrupt handling
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <plat/irq-uart.h>
-#include <plat/regs-serial.h>
-#include <plat/cpu.h>
-
-/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
- struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
- struct irq_chip *chip = irq_get_chip(irq);
- u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
- int base = uirq->base_irq;
-
- chained_irq_enter(chip, desc);
-
- if (pend & (1 << 0))
- generic_handle_irq(base);
- if (pend & (1 << 1))
- generic_handle_irq(base + 1);
- if (pend & (1 << 2))
- generic_handle_irq(base + 2);
- if (pend & (1 << 3))
- generic_handle_irq(base + 3);
-
- chained_irq_exit(chip, desc);
-}
-
-static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
-{
- void __iomem *reg_base = uirq->regs;
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- /* mask all interrupts at the start. */
- __raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
- gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,
- handle_level_irq);
-
- if (!gc) {
- pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n",
- __func__, uirq->base_irq);
- return;
- }
-
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->regs.ack = S3C64XX_UINTP;
- ct->regs.mask = S3C64XX_UINTM;
- irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-
- irq_set_handler_data(uirq->parent_irq, uirq);
- irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
-/**
- * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
- * @irq: The interrupt data for registering
- * @nr_irqs: The number of interrupt descriptions in @irq.
- *
- * Register the UART interrupts specified by @irq including the demuxing
- * routines. This supports the S3C6400 and newer style of devices.
- */
-void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs)
-{
- for (; nr_irqs > 0; nr_irqs--, irq++)
- s3c_init_uart_irq(irq);
-}
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's
2011-08-10 10:21 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler " Thomas Abraham
2011-08-10 10:21 ` [PATCH 2/2] ARM: SAMSUNG: Remove uart irq handling from plaform code Thomas Abraham
@ 2011-08-10 11:55 ` Alan Cox
1 sibling, 0 replies; 5+ messages in thread
From: Alan Cox @ 2011-08-10 11:55 UTC (permalink / raw)
To: Thomas Abraham
Cc: linux-serial, linux-arm-kernel, linux-samsung-soc, kgene.kim,
grant.likely, ben-linux
On Wed, 10 Aug 2011 15:51:19 +0530
Thomas Abraham <thomas.abraham@linaro.org> wrote:
> s3c64xx and later SoC's include the interrupt mask and pending
> registers in the uart controller, unlike the s3c24xx SoC's which have
> these registers in the interrupt controller. When the mask and
> pending registers are part of the uart controller, a unified
> interrupt handler can handle the tx/rx interrupt. With this, the
> static reservation of interrupt numbers for the uart tx/rx/err
> interrupts in the linux irq space is not required and simplifies
> adding device tree support.
Really only hardware changes so for the tty touching aspect of it
Acked-by: Alan Cox <alan@linux.intel.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] Update uart irq handling for s3c64xx and later SoC's
2011-08-10 10:21 [PATCH 0/2] Update uart irq handling for s3c64xx and later SoC's Thomas Abraham
2011-08-10 10:21 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler " Thomas Abraham
@ 2011-08-13 11:26 ` Tomasz Figa
1 sibling, 0 replies; 5+ messages in thread
From: Tomasz Figa @ 2011-08-13 11:26 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Thomas Abraham, linux-serial, kgene.kim, grant.likely,
linux-samsung-soc, ben-linux, alan
Hi Thomas,
On Wednesday 10 of August 2011 at 15:51:18, Thomas Abraham wrote:
> s3c64xx and later SoC's include the uart interrupt mask and pending
registers
> in the uart controller, unlike their s3c24xx predecessor. This allows the
> uart irq handling to be moved from the platform code to the driver. This
> patchset does this change and removes all the macros that will not be
> required with this update.
>
Your patches should solve the issue of system hanging on wake up because of
unacked (and unackable due to disabled UART bus clock) UART interrupts. So one
more reason to merge them.
My earlier description of the issue:
> I am experiencing a strange issue with UART ports on a Tiny6410 board, based
> on the S3C6410 SoC (hardware wise same as the Mini6410 supported by Linux),
> after enabling CONFIG_PM and suspending the SoC.
>
> After triggering a wakeup event, it resumes till arch_suspend_enable_irqs()
> called by suspend_enter() and starts to get hammered by infinite amounts of
> UART interrupts.
>
> I have tracked this down to disabling UART PCLK clock on suspend and the
> bootloader/reset/power down/whatever leaving the UART in an undefined state
> with interrupt bits set (specifically Tx interrupt), with the masked clock
> making it impossible to ack them by plat-samsung/irq-uart.c.
Best regards,
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-08-13 11:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-10 10:21 [PATCH 0/2] Update uart irq handling for s3c64xx and later SoC's Thomas Abraham
2011-08-10 10:21 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler " Thomas Abraham
2011-08-10 10:21 ` [PATCH 2/2] ARM: SAMSUNG: Remove uart irq handling from plaform code Thomas Abraham
2011-08-10 11:55 ` [PATCH 1/2] serial: samsung: Add unified interrupt handler for s3c64xx and later SoC's Alan Cox
2011-08-13 11:26 ` [PATCH 0/2] Update uart irq handling " Tomasz Figa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).