Topics

[RFC] uart: add ISR callback mechanism for UART drivers


Daniel Leung <daniel.leung@...>
 

The peripherals utilizing UART were required to register their own
ISR rountines. This means that all those peripherals drivers need
to know which IRQ line is attached to a UART controller, and all
the other config values required to register a ISR. This causes
scalibility issue as every board and peripherals have to define
those values.

Another reason for this patch is to support virtual serial ports.
Virtual serial ports do not have physical interrupt lines to
attach, and thus would not work.

This patch adds a simple callback mechanism, which calls a function
when UART interrupts are triggered. The low level plumbing still needs
to be done by the peripheral drivers, as these drivers may need to
access low level capability of UART to function correctly. This simply
moves the interrupt setup into the UART drivers themselves. By doing
this, the peripheral drivers do not need to know all the config values
to properly setup the interrupts and attaching the ISR. One drawback
is that this adds to the interrupt latency.

Note that this patch breaks backward compatibility in terms of
setting up interrupt for UART controller. How to use UART is still
the same.

This also addresses the following issues:

() UART driver for Atmel SAM3 currently does not support interrupts.
So remove the code from vector table. This will be updated when
there is interrupt support for the driver.
() Corrected some config options for Stellaris UART driver.

This was tested with samples/shell on Arduino 101, and on QEMU
(Cortex-M3 and x86).

Origin: Origin
Change-Id: Ib4593d8ccd711f4e97d388c7293205d213be1aec
Signed-off-by: Daniel Leung <daniel.leung(a)intel.com>
---
arch/arc/soc/quark_se_ss/Kconfig | 4 -
arch/arm/soc/atmel_sam3/Kconfig | 4 -
arch/arm/soc/atmel_sam3/irq_vector_table.c | 16 ---
arch/arm/soc/fsl_frdm_k64f/Kconfig | 8 --
arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c | 51 +++++++---
arch/arm/soc/ti_lm3s6965/Kconfig | 20 ++--
arch/arm/soc/ti_lm3s6965/irq_vector_table.c | 39 ++++---
arch/x86/soc/atom/Kconfig | 12 ---
arch/x86/soc/ia32/Kconfig | 12 ---
arch/x86/soc/quark_d2000/Kconfig | 12 ---
arch/x86/soc/quark_se/Kconfig | 8 --
arch/x86/soc/quark_x1000/Kconfig | 8 --
boards/arduino_101/Kconfig | 4 -
drivers/bluetooth/Kconfig | 14 ---
drivers/bluetooth/h4.c | 7 +-
drivers/bluetooth/h5.c | 8 +-
drivers/console/Kconfig | 28 ------
drivers/console/uart_console.c | 7 +-
drivers/console/uart_pipe.c | 8 +-
drivers/serial/uart_k20.c | 140 ++++++++++++++++++++++++++
drivers/serial/uart_k20.h | 26 +++++
drivers/serial/uart_ns16550.c | 79 +++++++++++++++
drivers/serial/uart_stellaris.c | 103 +++++++++++++++++++
drivers/serial/uart_stellaris.h | 26 +++++
include/drivers/console/uart_console.h | 2 -
include/drivers/console/uart_pipe.h | 9 --
include/uart.h | 41 ++++++++
27 files changed, 487 insertions(+), 209 deletions(-)
create mode 100644 drivers/serial/uart_k20.h
create mode 100644 drivers/serial/uart_stellaris.h

diff --git a/arch/arc/soc/quark_se_ss/Kconfig b/arch/arc/soc/quark_se_ss/Kconfig
index d6d1b90..827cafa 100644
--- a/arch/arc/soc/quark_se_ss/Kconfig
+++ b/arch/arc/soc/quark_se_ss/Kconfig
@@ -161,10 +161,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 42
-config UART_CONSOLE_IRQ_PRI
- default 1

endif

diff --git a/arch/arm/soc/atmel_sam3/Kconfig b/arch/arm/soc/atmel_sam3/Kconfig
index a7cf5cc..9b880e9 100644
--- a/arch/arm/soc/atmel_sam3/Kconfig
+++ b/arch/arm/soc/atmel_sam3/Kconfig
@@ -148,10 +148,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 8
-config UART_CONSOLE_IRQ_PRI
- default 3

endif # UART_CONSOLE

diff --git a/arch/arm/soc/atmel_sam3/irq_vector_table.c b/arch/arm/soc/atmel_sam3/irq_vector_table.c
index 24b1dcd..5f53773 100644
--- a/arch/arm/soc/atmel_sam3/irq_vector_table.c
+++ b/arch/arm/soc/atmel_sam3/irq_vector_table.c
@@ -32,11 +32,6 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
-#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */

@@ -50,20 +45,9 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
-{
- uart_console_isr(NULL);
- _IntExit();
-}
-#endif /* CONFIG_CONSOLE_HANDLER */
-
/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
};

#endif /* CONFIG_SW_ISR_TABLE */
diff --git a/arch/arm/soc/fsl_frdm_k64f/Kconfig b/arch/arm/soc/fsl_frdm_k64f/Kconfig
index 7ffec5e..7a1fa30 100644
--- a/arch/arm/soc/fsl_frdm_k64f/Kconfig
+++ b/arch/arm/soc/fsl_frdm_k64f/Kconfig
@@ -141,10 +141,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 31
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -152,10 +148,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 33
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c b/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
index d36abca..8c02ec4 100644
--- a/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
+++ b/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
@@ -31,15 +31,8 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
-#if defined(CONFIG_BLUETOOTH_UART)
-#include <soc.h>
-#include <bluetooth/uart.h>
-#endif /* CONFIG_BLUETOOTH_UART */
+#include <serial/uart_k20.h>

extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */
@@ -54,10 +47,34 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+static void _uart_k20_0_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_0));
+ _IntExit();
+}
+
+static void _uart_k20_1_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_1));
+ _IntExit();
+}
+
+static void _uart_k20_2_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_2));
+ _IntExit();
+}
+
+static void _uart_k20_3_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_3));
+ _IntExit();
+}
+
+static void _uart_k20_4_isr(void)
{
- uart_console_isr(NULL);
+ uart_k20_isr(DEVICE_GET(uart_k20_4));
_IntExit();
}
#endif /* CONFIG_CONSOLE_HANDLER */
@@ -73,11 +90,13 @@ static void _bt_uart_isr(void)
/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
-#if defined(CONFIG_BLUETOOTH_UART)
- [CONFIG_BLUETOOTH_UART_IRQ] = _bt_uart_isr,
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+ [CONFIG_UART_K20_PORT_0_IRQ] = _uart_k20_0_isr,
+ [CONFIG_UART_K20_PORT_1_IRQ] = _uart_k20_1_isr,
+ [CONFIG_UART_K20_PORT_2_IRQ] = _uart_k20_2_isr,
+ [CONFIG_UART_K20_PORT_3_IRQ] = _uart_k20_3_isr,
+ [CONFIG_UART_K20_PORT_4_IRQ] = _uart_k20_4_isr,
#endif
};

diff --git a/arch/arm/soc/ti_lm3s6965/Kconfig b/arch/arm/soc/ti_lm3s6965/Kconfig
index a9b32a2..fa643ba 100644
--- a/arch/arm/soc/ti_lm3s6965/Kconfig
+++ b/arch/arm/soc/ti_lm3s6965/Kconfig
@@ -66,7 +66,9 @@ if UART_STELLARIS_PORT_0
config UART_STELLARIS_PORT_0_BASE_ADDR
default 0x4000C000
config UART_STELLARIS_PORT_0_IRQ
- default 6
+ default 5
+config UART_STELLARIS_PORT_0_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_0_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_0_CLK_FREQ
@@ -81,6 +83,8 @@ config UART_STELLARIS_PORT_1_BASE_ADDR
default 0x4000D000
config UART_STELLARIS_PORT_1_IRQ
default 6
+config UART_STELLARIS_PORT_1_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_1_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_1_CLK_FREQ
@@ -94,6 +98,8 @@ config UART_STELLARIS_PORT_2_BASE_ADDR
default 0x4000E000
config UART_STELLARIS_PORT_2_IRQ
default 33
+config UART_STELLARIS_PORT_2_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_2_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_2_CLK_FREQ
@@ -106,10 +112,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 5
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -117,10 +119,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 6
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -128,10 +126,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_2"
-config UART_PIPE_IRQ
- default 33
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/arm/soc/ti_lm3s6965/irq_vector_table.c b/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
index d36abca..4d931f6 100644
--- a/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
+++ b/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
@@ -31,15 +31,8 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
-#if defined(CONFIG_BLUETOOTH_UART)
-#include <soc.h>
-#include <bluetooth/uart.h>
-#endif /* CONFIG_BLUETOOTH_UART */
+#include <serial/uart_stellaris.h>

extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */
@@ -54,30 +47,34 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+static void _uart_stellaris_port_0_isr(void)
+{
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris0));
+ _IntExit();
+}
+
+static void _uart_stellaris_port_1_isr(void)
{
- uart_console_isr(NULL);
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris1));
_IntExit();
}
-#endif /* CONFIG_CONSOLE_HANDLER */

-#if defined(CONFIG_BLUETOOTH_UART)
-static void _bt_uart_isr(void)
+static void _uart_stellaris_port_2_isr(void)
{
- bt_uart_isr(NULL);
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris2));
_IntExit();
}
-#endif /* CONFIG_BLUETOOTH_UART */
+#endif /* CONFIG_UART_INTERRUPT_DRIVEN */

/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
-#if defined(CONFIG_BLUETOOTH_UART)
- [CONFIG_BLUETOOTH_UART_IRQ] = _bt_uart_isr,
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+ [UART_STELLARIS_PORT_0_IRQ] = _uart_stellaris_port_0_isr,
+ [UART_STELLARIS_PORT_1_IRQ] = _uart_stellaris_port_1_isr,
+ [UART_STELLARIS_PORT_2_IRQ] = _uart_stellaris_port_2_isr,
#endif
};

diff --git a/arch/x86/soc/atom/Kconfig b/arch/x86/soc/atom/Kconfig
index c9b7f5f..f085985 100644
--- a/arch/x86/soc/atom/Kconfig
+++ b/arch/x86/soc/atom/Kconfig
@@ -105,10 +105,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 4
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -116,10 +112,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 3
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -127,10 +119,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 3
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/ia32/Kconfig b/arch/x86/soc/ia32/Kconfig
index f9916ba..6025697 100644
--- a/arch/x86/soc/ia32/Kconfig
+++ b/arch/x86/soc/ia32/Kconfig
@@ -105,10 +105,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 4
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -116,10 +112,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 3
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -127,10 +119,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 3
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_d2000/Kconfig b/arch/x86/soc/quark_d2000/Kconfig
index da8a1be..5d11114 100644
--- a/arch/x86/soc/quark_d2000/Kconfig
+++ b/arch/x86/soc/quark_d2000/Kconfig
@@ -127,10 +127,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 8
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -138,10 +134,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 6
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -149,10 +141,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 6
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_se/Kconfig b/arch/x86/soc/quark_se/Kconfig
index a17110d..8922f2d 100644
--- a/arch/x86/soc/quark_se/Kconfig
+++ b/arch/x86/soc/quark_se/Kconfig
@@ -376,10 +376,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 6
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -387,10 +383,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 38
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_x1000/Kconfig b/arch/x86/soc/quark_x1000/Kconfig
index ed7514d..3357d2c 100644
--- a/arch/x86/soc/quark_x1000/Kconfig
+++ b/arch/x86/soc/quark_x1000/Kconfig
@@ -343,10 +343,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 17
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -354,10 +350,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 17
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/boards/arduino_101/Kconfig b/boards/arduino_101/Kconfig
index 8d047dd..dafed3d 100644
--- a/boards/arduino_101/Kconfig
+++ b/boards/arduino_101/Kconfig
@@ -22,10 +22,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default UART_NS16550_PORT_1_NAME
-config UART_PIPE_IRQ
- default UART_NS16550_PORT_1_IRQ
-config UART_PIPE_IRQ_PRI
- default UART_NS16550_PORT_1_IRQ_PRI

endif

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c48e3f5..879dd47 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -71,20 +71,6 @@ config BLUETOOTH_UART_ON_DEV_NAME
This option specifies the name of UART device to be used
for Bluetooth.

-config BLUETOOTH_UART_IRQ
- int "IRQ of UART Device for Bluetooth"
- depends on BLUETOOTH_UART
- help
- This option specifies the IRQ of UART device to be used
- for Bluetooth.
-
-config BLUETOOTH_UART_IRQ_PRI
- int "IRQ Priority of UART Device for Bluetooth"
- depends on BLUETOOTH_UART
- help
- This option specifies the IRQ priority of UART device to be used
- for Bluetooth.
-
# Headroom that the driver needs for sending and receiving buffers.
# Add a new 'default' entry for each new driver.

diff --git a/drivers/bluetooth/h4.c b/drivers/bluetooth/h4.c
index 6fbf7f2..0fc3abd 100644
--- a/drivers/bluetooth/h4.c
+++ b/drivers/bluetooth/h4.c
@@ -123,7 +123,7 @@ static struct net_buf *h4_acl_recv(int *remaining)
return buf;
}

-void bt_uart_isr(void *unused)
+static void bt_uart_isr(struct device *unused)
{
static struct net_buf *buf;
static int remaining;
@@ -223,9 +223,6 @@ static int h4_open(void)

uart_irq_rx_disable(h4_dev);
uart_irq_tx_disable(h4_dev);
- IRQ_CONNECT(CONFIG_BLUETOOTH_UART_IRQ, CONFIG_BLUETOOTH_UART_IRQ_PRI,
- bt_uart_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_BLUETOOTH_UART_IRQ);

/* Drain the fifo */
while (uart_irq_rx_ready(h4_dev)) {
@@ -234,6 +231,8 @@ static int h4_open(void)
uart_fifo_read(h4_dev, &c, 1);
}

+ uart_irq_callback_set(h4_dev, bt_uart_isr);
+
uart_irq_rx_enable(h4_dev);

return 0;
diff --git a/drivers/bluetooth/h5.c b/drivers/bluetooth/h5.c
index 5a6a4ba..562b0e7 100644
--- a/drivers/bluetooth/h5.c
+++ b/drivers/bluetooth/h5.c
@@ -445,7 +445,7 @@ static void h5_process_complete_packet(uint8_t *hdr)
}
}

-void bt_uart_isr(void *unused)
+static void bt_uart_isr(struct device *unused)
{
static int remaining;
uint8_t byte;
@@ -748,10 +748,6 @@ static int h5_open(void)
uart_irq_rx_disable(h5_dev);
uart_irq_tx_disable(h5_dev);

- IRQ_CONNECT(CONFIG_BLUETOOTH_UART_IRQ, CONFIG_BLUETOOTH_UART_IRQ_PRI,
- bt_uart_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_BLUETOOTH_UART_IRQ);
-
/* Drain the fifo */
while (uart_irq_rx_ready(h5_dev)) {
unsigned char c;
@@ -759,6 +755,8 @@ static int h5_open(void)
uart_fifo_read(h5_dev, &c, 1);
}

+ uart_irq_callback_set(h5_dev, bt_uart_isr);
+
h5_init();

uart_irq_rx_enable(h5_dev);
diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig
index c8dc686..0638f70 100644
--- a/drivers/console/Kconfig
+++ b/drivers/console/Kconfig
@@ -73,20 +73,6 @@ config UART_CONSOLE_ON_DEV_NAME
This option specifies the name of UART device to be used for
UART console.

-config UART_CONSOLE_IRQ
- int "IRQ of UART Device for UART Console"
- depends on UART_CONSOLE
- help
- This option specifies the IRQ of UART device to be used for
- UART console.
-
-config UART_CONSOLE_IRQ_PRI
- int "IRQ of UART Device for UART Console"
- depends on UART_CONSOLE
- help
- This option specifies the IRQ priorityof UART device to be
- used for UART console.
-
config UART_CONSOLE_PRIORITY
int
prompt "Init priority"
@@ -160,18 +146,4 @@ config UART_PIPE_ON_DEV_NAME
This option specifies the name of UART device to be used
for pipe UART.

-config UART_PIPE_IRQ
- int "IRQ for pipe UART"
- depends on UART_PIPE
- help
- This option specifies the IRQ of UART device to be used
- for pipe UART.
-
-config UART_PIPE_IRQ_PRI
- int "IRQ Priority for pipe UART"
- depends on UART_PIPE
- help
- This option specifies the IRQ priority of UART device
- to be used for pipe UART.
-
endif
diff --git a/drivers/console/uart_console.c b/drivers/console/uart_console.c
index 762b7aa..72c5631 100644
--- a/drivers/console/uart_console.c
+++ b/drivers/console/uart_console.c
@@ -278,7 +278,7 @@ ansi_cmd:
atomic_clear_bit(&esc_state, ESC_ANSI);
}

-void uart_console_isr(void *unused)
+void uart_console_isr(struct device *unused)
{
ARG_UNUSED(unused);

@@ -373,9 +373,8 @@ static void console_input_init(void)

uart_irq_rx_disable(uart_console_dev);
uart_irq_tx_disable(uart_console_dev);
- IRQ_CONNECT(CONFIG_UART_CONSOLE_IRQ, CONFIG_UART_CONSOLE_IRQ_PRI,
- uart_console_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_UART_CONSOLE_IRQ);
+
+ uart_irq_callback_set(uart_console_dev, uart_console_isr);

/* Drain the fifo */
while (uart_irq_rx_ready(uart_console_dev)) {
diff --git a/drivers/console/uart_pipe.c b/drivers/console/uart_pipe.c
index f56f9b1..c8c89ae 100644
--- a/drivers/console/uart_pipe.c
+++ b/drivers/console/uart_pipe.c
@@ -36,7 +36,7 @@ static size_t recv_buf_len;
static uart_pipe_recv_cb app_cb;
static size_t recv_off;

-void uart_pipe_isr(void *unused)
+static void uart_pipe_isr(struct device *unused)
{
ARG_UNUSED(unused);

@@ -77,10 +77,6 @@ static void uart_pipe_setup(struct device *uart)
uart_irq_rx_disable(uart);
uart_irq_tx_disable(uart);

- IRQ_CONNECT(CONFIG_UART_PIPE_IRQ, CONFIG_UART_PIPE_IRQ_PRI,
- uart_pipe_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_UART_PIPE_IRQ);
-
/* Drain the fifo */
while (uart_irq_rx_ready(uart)) {
unsigned char c;
@@ -88,6 +84,8 @@ static void uart_pipe_setup(struct device *uart)
uart_fifo_read(uart, &c, 1);
}

+ uart_irq_callback_set(uart, uart_pipe_isr);
+
uart_irq_rx_enable(uart);
}

diff --git a/drivers/serial/uart_k20.c b/drivers/serial/uart_k20.c
index 3f0985e..5c261f0 100644
--- a/drivers/serial/uart_k20.c
+++ b/drivers/serial/uart_k20.c
@@ -31,6 +31,7 @@
#include <toolchain.h>
#include <sections.h>

+#include "uart_k20.h"
#include "uart_k20_priv.h"

/* convenience defines */
@@ -45,6 +46,10 @@
/* Device data structure */
struct uart_k20_dev_data_t {
uint32_t baud_rate; /* Baud rate */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_callback_t cb; /**< Callback function pointer */
+#endif
};

static struct uart_driver_api uart_k20_driver_api;
@@ -90,6 +95,10 @@ static int uart_k20_init(struct device *dev)
/* restore interrupt state */
irq_unlock(old_level);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ dev_cfg->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_k20_driver_api;

return DEV_OK;
@@ -339,6 +348,41 @@ static int uart_k20_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_k20_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_k20_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+void uart_k20_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_k20_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */


@@ -360,6 +404,7 @@ static struct uart_driver_api uart_k20_driver_api = {
.irq_err_disable = uart_k20_irq_err_disable,
.irq_is_pending = uart_k20_irq_is_pending,
.irq_update = uart_k20_irq_update,
+ .irq_callback_set = uart_k20_irq_callback_set,

#endif
};
@@ -367,9 +412,17 @@ static struct uart_driver_api uart_k20_driver_api = {

#ifdef CONFIG_UART_K20_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_0 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_0_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_0 = {
@@ -380,13 +433,32 @@ DEVICE_INIT(uart_k20_0, CONFIG_UART_K20_PORT_0_NAME, &uart_k20_init,
&uart_k20_dev_data_0, &uart_k20_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_0_IRQ,
+ CONFIG_UART_K20_PORT_0_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_0 */

#ifdef CONFIG_UART_K20_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_1 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_1_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_1 = {
@@ -397,13 +469,32 @@ DEVICE_INIT(uart_k20_1, CONFIG_UART_K20_PORT_1_NAME, &uart_k20_init,
&uart_k20_dev_data_1, &uart_k20_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_1_IRQ,
+ CONFIG_UART_K20_PORT_1_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_1 */

#ifdef CONFIG_UART_K20_PORT_2

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_2 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_2_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_2_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_2,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_2 = {
@@ -414,13 +505,32 @@ DEVICE_INIT(uart_k20_2, CONFIG_UART_K20_PORT_2_NAME, &uart_k20_init,
&uart_k20_dev_data_2, &uart_k20_dev_cfg_2,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_2_IRQ,
+ CONFIG_UART_K20_PORT_2_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_2),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_2_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_2 */

#ifdef CONFIG_UART_K20_PORT_3

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_3(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_3 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_3_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_3_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_3,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_3 = {
@@ -431,13 +541,32 @@ DEVICE_INIT(uart_k20_3, CONFIG_UART_K20_PORT_3_NAME, &uart_k20_init,
&uart_k20_dev_data_3, &uart_k20_dev_cfg_3,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_3(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_3_IRQ,
+ CONFIG_UART_K20_PORT_3_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_3),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_3_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_3 */

#ifdef CONFIG_UART_K20_PORT_4

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_4(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_4 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_4_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_4_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_4,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_4 = {
@@ -448,4 +577,15 @@ DEVICE_INIT(uart_k20_4, CONFIG_UART_K20_PORT_4_NAME, &uart_k20_init,
&uart_k20_dev_data_4, &uart_k20_dev_cfg_4,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_4(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_4_IRQ,
+ CONFIG_UART_K20_PORT_4_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_4),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_4_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_4 */
diff --git a/drivers/serial/uart_k20.h b/drivers/serial/uart_k20.h
new file mode 100644
index 0000000..ca92859
--- /dev/null
+++ b/drivers/serial/uart_k20.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file UART header file for the K20 family of microprocessors..
+ */
+
+#ifndef _UART_K20_H_
+#define _UART_K20_H_
+
+void uart_k20_isr(void *arg);
+
+#endif /* _UART_K20_H_ */
diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c
index 543f7a0..f6b0b2e 100644
--- a/drivers/serial/uart_ns16550.c
+++ b/drivers/serial/uart_ns16550.c
@@ -210,6 +210,7 @@ struct uart_ns16550_dev_data_t {

#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uint8_t iir_cache; /**< cache of IIR since it clears when read */
+ uart_irq_callback_t cb; /**< Callback function pointer */
#endif

#ifdef CONFIG_UART_NS16550_DLF
@@ -336,6 +337,10 @@ static int uart_ns16550_init(struct device *dev)

irq_unlock(old_level);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ DEV_CFG(dev)->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_ns16550_driver_api;

return DEV_OK;
@@ -576,6 +581,41 @@ static int uart_ns16550_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_ns16550_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+static void uart_ns16550_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */

#ifdef CONFIG_UART_NS16550_LINE_CTRL
@@ -671,6 +711,7 @@ static struct uart_driver_api uart_ns16550_driver_api = {
.irq_err_disable = uart_ns16550_irq_err_disable,
.irq_is_pending = uart_ns16550_irq_is_pending,
.irq_update = uart_ns16550_irq_update,
+ .irq_callback_set = uart_ns16550_irq_callback_set,

#endif

@@ -685,6 +726,10 @@ static struct uart_driver_api uart_ns16550_driver_api = {

#ifdef CONFIG_UART_NS16550_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
struct uart_device_config uart_ns16550_dev_cfg_0 = {
.port = CONFIG_UART_NS16550_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_NS16550_PORT_0_CLK_FREQ,
@@ -698,6 +743,10 @@ struct uart_device_config uart_ns16550_dev_cfg_0 = {
.pci_dev.function = CONFIG_UART_NS16550_PORT_0_PCI_FUNC,
.pci_dev.bar = CONFIG_UART_NS16550_PORT_0_PCI_BAR,
#endif /* CONFIG_UART_NS16550_PORT_0_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_0 = {
@@ -713,10 +762,25 @@ DEVICE_INIT(uart_ns16550_0, CONFIG_UART_NS16550_PORT_0_NAME, &uart_ns16550_init,
&uart_ns16550_dev_data_0, &uart_ns16550_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_NS16550_PORT_0_IRQ,
+ CONFIG_UART_NS16550_PORT_0_IRQ_PRI,
+ uart_ns16550_isr, DEVICE_GET(uart_ns16550_0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_NS16550_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_NS16550_PORT_0 */

#ifdef CONFIG_UART_NS16550_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
struct uart_device_config uart_ns16550_dev_cfg_1 = {
.port = CONFIG_UART_NS16550_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_NS16550_PORT_1_CLK_FREQ,
@@ -730,6 +794,10 @@ struct uart_device_config uart_ns16550_dev_cfg_1 = {
.pci_dev.function = CONFIG_UART_NS16550_PORT_1_PCI_FUNC,
.pci_dev.bar = CONFIG_UART_NS16550_PORT_1_PCI_BAR,
#endif /* CONFIG_UART_NS16550_PORT_1_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_1 = {
@@ -745,4 +813,15 @@ DEVICE_INIT(uart_ns16550_1, CONFIG_UART_NS16550_PORT_1_NAME, &uart_ns16550_init,
&uart_ns16550_dev_data_1, &uart_ns16550_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_NS16550_PORT_1_IRQ,
+ CONFIG_UART_NS16550_PORT_1_IRQ_PRI,
+ uart_ns16550_isr, DEVICE_GET(uart_ns16550_1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_NS16550_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_NS16550_PORT_1 */
diff --git a/drivers/serial/uart_stellaris.c b/drivers/serial/uart_stellaris.c
index 3a6ea16..eaaa10e 100644
--- a/drivers/serial/uart_stellaris.c
+++ b/drivers/serial/uart_stellaris.c
@@ -34,6 +34,8 @@
#include <uart.h>
#include <sections.h>

+#include "uart_stellaris.h"
+
/* definitions */

/* Stellaris UART module */
@@ -76,6 +78,10 @@ struct _uart {
/* Device data structure */
struct uart_stellaris_dev_data_t {
uint32_t baud_rate; /* Baud rate */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_callback_t cb; /**< Callback function pointer */
+#endif
};

/* convenience defines */
@@ -271,6 +277,10 @@ static int uart_stellaris_init(struct device *dev)
line_control_defaults_set(dev);
enable(dev);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ DEV_CFG(dev)->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_stellaris_driver_api;

return DEV_OK;
@@ -565,6 +575,41 @@ static int uart_stellaris_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_stellaris_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_stellaris_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+void uart_stellaris_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_stellaris_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */


@@ -586,6 +631,7 @@ static struct uart_driver_api uart_stellaris_driver_api = {
.irq_err_disable = uart_stellaris_irq_err_disable,
.irq_is_pending = uart_stellaris_irq_is_pending,
.irq_update = uart_stellaris_irq_update,
+ .irq_callback_set = uart_stellaris_irq_callback_set,

#endif
};
@@ -593,9 +639,17 @@ static struct uart_driver_api uart_stellaris_driver_api = {

#ifdef CONFIG_UART_STELLARIS_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_0 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_0_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_0 = {
@@ -606,13 +660,32 @@ DEVICE_INIT(uart_stellaris0, CONFIG_UART_STELLARIS_PORT_0_NAME, &uart_stellaris_
&uart_stellaris_dev_data_0, &uart_stellaris_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_0_IRQ,
+ CONFIG_UART_STELLARIS_PORT_0_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_0 */

#ifdef CONFIG_UART_STELLARIS_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_1 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_1_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_1 = {
@@ -623,13 +696,32 @@ DEVICE_INIT(uart_stellaris1, CONFIG_UART_STELLARIS_PORT_1_NAME, &uart_stellaris_
&uart_stellaris_dev_data_1, &uart_stellaris_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_1_IRQ,
+ CONFIG_UART_STELLARIS_PORT_1_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_1 */

#ifdef CONFIG_UART_STELLARIS_PORT_2

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_2 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_2_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_2_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_2,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_2 = {
@@ -640,4 +732,15 @@ DEVICE_INIT(uart_stellaris2, CONFIG_UART_STELLARIS_PORT_2_NAME, &uart_stellaris_
&uart_stellaris_dev_data_2, &uart_stellaris_dev_cfg_2,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_2_IRQ,
+ CONFIG_UART_STELLARIS_PORT_2_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris2),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_2_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_2 */
diff --git a/drivers/serial/uart_stellaris.h b/drivers/serial/uart_stellaris.h
new file mode 100644
index 0000000..4a14ef3
--- /dev/null
+++ b/drivers/serial/uart_stellaris.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file Header file for Stellaris UART.
+ */
+
+#ifndef _UART_STELLARIS_H_
+#define _UART_STELLARIS_H_
+
+void uart_console_isr(void *arg);
+
+#endif /* _UART_STELLARIS_H_ */
diff --git a/include/drivers/console/uart_console.h b/include/drivers/console/uart_console.h
index 4634e33..963e8af 100644
--- a/include/drivers/console/uart_console.h
+++ b/include/drivers/console/uart_console.h
@@ -46,8 +46,6 @@ struct uart_console_input {
*/
void uart_register_input(struct nano_fifo *avail, struct nano_fifo *lines);

-void uart_console_isr(void *unused);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/drivers/console/uart_pipe.h b/include/drivers/console/uart_pipe.h
index 3b7594a..2391bbd 100644
--- a/include/drivers/console/uart_pipe.h
+++ b/include/drivers/console/uart_pipe.h
@@ -62,15 +62,6 @@ void uart_pipe_register(uint8_t *buf, size_t len, uart_pipe_recv_cb cb);
*/
int uart_pipe_send(const uint8_t *data, int len);

-/** @brief Simple UART interrupt handler.
- *
- * This function is called from an interrupt and should not be called by
- * an application directly.
- *
- * @param unused unused
- */
-void uart_pipe_isr(void *unused);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/uart.h b/include/uart.h
index 66e5123..cba33c3 100644
--- a/include/uart.h
+++ b/include/uart.h
@@ -71,6 +71,16 @@ extern "C" {
*/
#define UART_ERROR_BREAK (1 << 3)

+/**
+ * @brief Define the application callback function signature for UART.
+ *
+ * @param port Device struct for the UART device.
+ */
+typedef void (*uart_irq_callback_t)(struct device *port);
+
+/* For configuring IRQ on each individual UART device. Internal use only. */
+typedef void (*uart_irq_config_func_t)(struct device *port);
+
/** @brief UART device configuration.*/
struct uart_device_config {
/**
@@ -90,6 +100,10 @@ struct uart_device_config {
#ifdef CONFIG_PCI
struct pci_dev_info pci_dev;
#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_config_func_t irq_config_func;
+#endif
};

/** @brief Driver API structure. */
@@ -145,6 +159,9 @@ struct uart_driver_api {
/** Interrupt driven input hook function */
int (*irq_input_hook)(struct device *dev, uint8_t byte);

+ /** Set the callback function */
+ void (*irq_callback_set)(struct device *dev, uart_irq_callback_t cb);
+
#endif

#ifdef CONFIG_UART_LINE_CTRL
@@ -516,6 +533,30 @@ static inline void uart_irq_input_hook_set(struct device *dev,
}
}

+
+/**
+ * @brief Set the IRQ callback function pointer.
+ *
+ * This sets up the callback for IRQ. When an IRQ is triggered,
+ * the specified function will be called.
+ *
+ * @param dev UART device structure.
+ * @param cb Pointer to the callback function.
+ *
+ * @return N/A
+ */
+static inline void uart_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_driver_api *api;
+
+ api = (struct uart_driver_api *)dev->driver_api;
+
+ if ((api != NULL) && (api->irq_callback_set != NULL)) {
+ api->irq_callback_set(dev, cb);
+ }
+}
+
#endif

#ifdef CONFIG_UART_LINE_CTRL
--
2.7.2


Dirk Brandewie <dirk.j.brandewie@...>
 

On 02/29/2016 03:51 PM, Daniel Leung wrote:
The peripherals utilizing UART were required to register their own
ISR rountines. This means that all those peripherals drivers need
to know which IRQ line is attached to a UART controller, and all
the other config values required to register a ISR. This causes
scalibility issue as every board and peripherals have to define
those values.

Another reason for this patch is to support virtual serial ports.
Virtual serial ports do not have physical interrupt lines to
attach, and thus would not work.

This patch adds a simple callback mechanism, which calls a function
when UART interrupts are triggered. The low level plumbing still needs
to be done by the peripheral drivers, as these drivers may need to
access low level capability of UART to function correctly. This simply
moves the interrupt setup into the UART drivers themselves. By doing
this, the peripheral drivers do not need to know all the config values
to properly setup the interrupts and attaching the ISR. One drawback
is that this adds to the interrupt latency.

Note that this patch breaks backward compatibility in terms of
setting up interrupt for UART controller. How to use UART is still
the same.

This also addresses the following issues:

() UART driver for Atmel SAM3 currently does not support interrupts.
So remove the code from vector table. This will be updated when
there is interrupt support for the driver.
() Corrected some config options for Stellaris UART driver.

This was tested with samples/shell on Arduino 101, and on QEMU
(Cortex-M3 and x86).

Origin: Origin
Change-Id: Ib4593d8ccd711f4e97d388c7293205d213be1aec
Signed-off-by: Daniel Leung <daniel.leung(a)intel.com>
Acked-by: Dirk Brandewie <dirk.j.brandewie(a)intel.com>

---
arch/arc/soc/quark_se_ss/Kconfig | 4 -
arch/arm/soc/atmel_sam3/Kconfig | 4 -
arch/arm/soc/atmel_sam3/irq_vector_table.c | 16 ---
arch/arm/soc/fsl_frdm_k64f/Kconfig | 8 --
arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c | 51 +++++++---
arch/arm/soc/ti_lm3s6965/Kconfig | 20 ++--
arch/arm/soc/ti_lm3s6965/irq_vector_table.c | 39 ++++---
arch/x86/soc/atom/Kconfig | 12 ---
arch/x86/soc/ia32/Kconfig | 12 ---
arch/x86/soc/quark_d2000/Kconfig | 12 ---
arch/x86/soc/quark_se/Kconfig | 8 --
arch/x86/soc/quark_x1000/Kconfig | 8 --
boards/arduino_101/Kconfig | 4 -
drivers/bluetooth/Kconfig | 14 ---
drivers/bluetooth/h4.c | 7 +-
drivers/bluetooth/h5.c | 8 +-
drivers/console/Kconfig | 28 ------
drivers/console/uart_console.c | 7 +-
drivers/console/uart_pipe.c | 8 +-
drivers/serial/uart_k20.c | 140 ++++++++++++++++++++++++++
drivers/serial/uart_k20.h | 26 +++++
drivers/serial/uart_ns16550.c | 79 +++++++++++++++
drivers/serial/uart_stellaris.c | 103 +++++++++++++++++++
drivers/serial/uart_stellaris.h | 26 +++++
include/drivers/console/uart_console.h | 2 -
include/drivers/console/uart_pipe.h | 9 --
include/uart.h | 41 ++++++++
27 files changed, 487 insertions(+), 209 deletions(-)
create mode 100644 drivers/serial/uart_k20.h
create mode 100644 drivers/serial/uart_stellaris.h

diff --git a/arch/arc/soc/quark_se_ss/Kconfig b/arch/arc/soc/quark_se_ss/Kconfig
index d6d1b90..827cafa 100644
--- a/arch/arc/soc/quark_se_ss/Kconfig
+++ b/arch/arc/soc/quark_se_ss/Kconfig
@@ -161,10 +161,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 42
-config UART_CONSOLE_IRQ_PRI
- default 1

endif

diff --git a/arch/arm/soc/atmel_sam3/Kconfig b/arch/arm/soc/atmel_sam3/Kconfig
index a7cf5cc..9b880e9 100644
--- a/arch/arm/soc/atmel_sam3/Kconfig
+++ b/arch/arm/soc/atmel_sam3/Kconfig
@@ -148,10 +148,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 8
-config UART_CONSOLE_IRQ_PRI
- default 3

endif # UART_CONSOLE

diff --git a/arch/arm/soc/atmel_sam3/irq_vector_table.c b/arch/arm/soc/atmel_sam3/irq_vector_table.c
index 24b1dcd..5f53773 100644
--- a/arch/arm/soc/atmel_sam3/irq_vector_table.c
+++ b/arch/arm/soc/atmel_sam3/irq_vector_table.c
@@ -32,11 +32,6 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
-#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */

@@ -50,20 +45,9 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
-{
- uart_console_isr(NULL);
- _IntExit();
-}
-#endif /* CONFIG_CONSOLE_HANDLER */
-
/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
};

#endif /* CONFIG_SW_ISR_TABLE */
diff --git a/arch/arm/soc/fsl_frdm_k64f/Kconfig b/arch/arm/soc/fsl_frdm_k64f/Kconfig
index 7ffec5e..7a1fa30 100644
--- a/arch/arm/soc/fsl_frdm_k64f/Kconfig
+++ b/arch/arm/soc/fsl_frdm_k64f/Kconfig
@@ -141,10 +141,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 31
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -152,10 +148,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 33
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c b/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
index d36abca..8c02ec4 100644
--- a/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
+++ b/arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c
@@ -31,15 +31,8 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
-#if defined(CONFIG_BLUETOOTH_UART)
-#include <soc.h>
-#include <bluetooth/uart.h>
-#endif /* CONFIG_BLUETOOTH_UART */
+#include <serial/uart_k20.h>

extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */
@@ -54,10 +47,34 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+static void _uart_k20_0_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_0));
+ _IntExit();
+}
+
+static void _uart_k20_1_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_1));
+ _IntExit();
+}
+
+static void _uart_k20_2_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_2));
+ _IntExit();
+}
+
+static void _uart_k20_3_isr(void)
+{
+ uart_k20_isr(DEVICE_GET(uart_k20_3));
+ _IntExit();
+}
+
+static void _uart_k20_4_isr(void)
{
- uart_console_isr(NULL);
+ uart_k20_isr(DEVICE_GET(uart_k20_4));
_IntExit();
}
#endif /* CONFIG_CONSOLE_HANDLER */
@@ -73,11 +90,13 @@ static void _bt_uart_isr(void)
/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
-#if defined(CONFIG_BLUETOOTH_UART)
- [CONFIG_BLUETOOTH_UART_IRQ] = _bt_uart_isr,
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+ [CONFIG_UART_K20_PORT_0_IRQ] = _uart_k20_0_isr,
+ [CONFIG_UART_K20_PORT_1_IRQ] = _uart_k20_1_isr,
+ [CONFIG_UART_K20_PORT_2_IRQ] = _uart_k20_2_isr,
+ [CONFIG_UART_K20_PORT_3_IRQ] = _uart_k20_3_isr,
+ [CONFIG_UART_K20_PORT_4_IRQ] = _uart_k20_4_isr,
#endif
};

diff --git a/arch/arm/soc/ti_lm3s6965/Kconfig b/arch/arm/soc/ti_lm3s6965/Kconfig
index a9b32a2..fa643ba 100644
--- a/arch/arm/soc/ti_lm3s6965/Kconfig
+++ b/arch/arm/soc/ti_lm3s6965/Kconfig
@@ -66,7 +66,9 @@ if UART_STELLARIS_PORT_0
config UART_STELLARIS_PORT_0_BASE_ADDR
default 0x4000C000
config UART_STELLARIS_PORT_0_IRQ
- default 6
+ default 5
+config UART_STELLARIS_PORT_0_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_0_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_0_CLK_FREQ
@@ -81,6 +83,8 @@ config UART_STELLARIS_PORT_1_BASE_ADDR
default 0x4000D000
config UART_STELLARIS_PORT_1_IRQ
default 6
+config UART_STELLARIS_PORT_1_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_1_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_1_CLK_FREQ
@@ -94,6 +98,8 @@ config UART_STELLARIS_PORT_2_BASE_ADDR
default 0x4000E000
config UART_STELLARIS_PORT_2_IRQ
default 33
+config UART_STELLARIS_PORT_2_IRQ_PRI
+ default 3
config UART_STELLARIS_PORT_2_BAUD_RATE
default 115200
config UART_STELLARIS_PORT_2_CLK_FREQ
@@ -106,10 +112,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 5
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -117,10 +119,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 6
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -128,10 +126,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_2"
-config UART_PIPE_IRQ
- default 33
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/arm/soc/ti_lm3s6965/irq_vector_table.c b/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
index d36abca..4d931f6 100644
--- a/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
+++ b/arch/arm/soc/ti_lm3s6965/irq_vector_table.c
@@ -31,15 +31,8 @@
#include <toolchain.h>
#include <sections.h>

-#if defined(CONFIG_CONSOLE_HANDLER)
#include <soc.h>
-#include <console/uart_console.h>
-#endif /* CONFIG_CONSOLE_HANDLER */
-
-#if defined(CONFIG_BLUETOOTH_UART)
-#include <soc.h>
-#include <bluetooth/uart.h>
-#endif /* CONFIG_BLUETOOTH_UART */
+#include <serial/uart_stellaris.h>

extern void _isr_wrapper(void);
typedef void (*vth)(void); /* Vector Table Handler */
@@ -54,30 +47,34 @@ vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {

extern void _irq_spurious(void);

-#if defined(CONFIG_CONSOLE_HANDLER)
-static void _uart_console_isr(void)
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+static void _uart_stellaris_port_0_isr(void)
+{
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris0));
+ _IntExit();
+}
+
+static void _uart_stellaris_port_1_isr(void)
{
- uart_console_isr(NULL);
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris1));
_IntExit();
}
-#endif /* CONFIG_CONSOLE_HANDLER */

-#if defined(CONFIG_BLUETOOTH_UART)
-static void _bt_uart_isr(void)
+static void _uart_stellaris_port_2_isr(void)
{
- bt_uart_isr(NULL);
+ uart_stellaris_isr(DEVICE_GET(uart_stellaris2));
_IntExit();
}
-#endif /* CONFIG_BLUETOOTH_UART */
+#endif /* CONFIG_UART_INTERRUPT_DRIVEN */

/* placeholders: fill with real ISRs */
vth __irq_vector_table _irq_vector_table[CONFIG_NUM_IRQS] = {
[0 ...(CONFIG_NUM_IRQS - 1)] = _irq_spurious,
-#if defined(CONFIG_CONSOLE_HANDLER)
- [CONFIG_UART_CONSOLE_IRQ] = _uart_console_isr,
-#endif
-#if defined(CONFIG_BLUETOOTH_UART)
- [CONFIG_BLUETOOTH_UART_IRQ] = _bt_uart_isr,
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+ [UART_STELLARIS_PORT_0_IRQ] = _uart_stellaris_port_0_isr,
+ [UART_STELLARIS_PORT_1_IRQ] = _uart_stellaris_port_1_isr,
+ [UART_STELLARIS_PORT_2_IRQ] = _uart_stellaris_port_2_isr,
#endif
};

diff --git a/arch/x86/soc/atom/Kconfig b/arch/x86/soc/atom/Kconfig
index c9b7f5f..f085985 100644
--- a/arch/x86/soc/atom/Kconfig
+++ b/arch/x86/soc/atom/Kconfig
@@ -105,10 +105,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 4
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -116,10 +112,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 3
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -127,10 +119,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 3
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/ia32/Kconfig b/arch/x86/soc/ia32/Kconfig
index f9916ba..6025697 100644
--- a/arch/x86/soc/ia32/Kconfig
+++ b/arch/x86/soc/ia32/Kconfig
@@ -105,10 +105,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 4
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -116,10 +112,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 3
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -127,10 +119,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 3
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_d2000/Kconfig b/arch/x86/soc/quark_d2000/Kconfig
index da8a1be..5d11114 100644
--- a/arch/x86/soc/quark_d2000/Kconfig
+++ b/arch/x86/soc/quark_d2000/Kconfig
@@ -127,10 +127,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_0"
-config UART_CONSOLE_IRQ
- default 8
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -138,10 +134,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 6
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

@@ -149,10 +141,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default "UART_1"
-config UART_PIPE_IRQ
- default 6
-config UART_PIPE_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_se/Kconfig b/arch/x86/soc/quark_se/Kconfig
index a17110d..8922f2d 100644
--- a/arch/x86/soc/quark_se/Kconfig
+++ b/arch/x86/soc/quark_se/Kconfig
@@ -376,10 +376,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 6
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -387,10 +383,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 38
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/arch/x86/soc/quark_x1000/Kconfig b/arch/x86/soc/quark_x1000/Kconfig
index ed7514d..3357d2c 100644
--- a/arch/x86/soc/quark_x1000/Kconfig
+++ b/arch/x86/soc/quark_x1000/Kconfig
@@ -343,10 +343,6 @@ if UART_CONSOLE

config UART_CONSOLE_ON_DEV_NAME
default "UART_1"
-config UART_CONSOLE_IRQ
- default 17
-config UART_CONSOLE_IRQ_PRI
- default 3

endif

@@ -354,10 +350,6 @@ if BLUETOOTH_UART

config BLUETOOTH_UART_ON_DEV_NAME
default "UART_1"
-config BLUETOOTH_UART_IRQ
- default 17
-config BLUETOOTH_UART_IRQ_PRI
- default 3

endif

diff --git a/boards/arduino_101/Kconfig b/boards/arduino_101/Kconfig
index 8d047dd..dafed3d 100644
--- a/boards/arduino_101/Kconfig
+++ b/boards/arduino_101/Kconfig
@@ -22,10 +22,6 @@ if UART_PIPE

config UART_PIPE_ON_DEV_NAME
default UART_NS16550_PORT_1_NAME
-config UART_PIPE_IRQ
- default UART_NS16550_PORT_1_IRQ
-config UART_PIPE_IRQ_PRI
- default UART_NS16550_PORT_1_IRQ_PRI

endif

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c48e3f5..879dd47 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -71,20 +71,6 @@ config BLUETOOTH_UART_ON_DEV_NAME
This option specifies the name of UART device to be used
for Bluetooth.

-config BLUETOOTH_UART_IRQ
- int "IRQ of UART Device for Bluetooth"
- depends on BLUETOOTH_UART
- help
- This option specifies the IRQ of UART device to be used
- for Bluetooth.
-
-config BLUETOOTH_UART_IRQ_PRI
- int "IRQ Priority of UART Device for Bluetooth"
- depends on BLUETOOTH_UART
- help
- This option specifies the IRQ priority of UART device to be used
- for Bluetooth.
-
# Headroom that the driver needs for sending and receiving buffers.
# Add a new 'default' entry for each new driver.

diff --git a/drivers/bluetooth/h4.c b/drivers/bluetooth/h4.c
index 6fbf7f2..0fc3abd 100644
--- a/drivers/bluetooth/h4.c
+++ b/drivers/bluetooth/h4.c
@@ -123,7 +123,7 @@ static struct net_buf *h4_acl_recv(int *remaining)
return buf;
}

-void bt_uart_isr(void *unused)
+static void bt_uart_isr(struct device *unused)
{
static struct net_buf *buf;
static int remaining;
@@ -223,9 +223,6 @@ static int h4_open(void)

uart_irq_rx_disable(h4_dev);
uart_irq_tx_disable(h4_dev);
- IRQ_CONNECT(CONFIG_BLUETOOTH_UART_IRQ, CONFIG_BLUETOOTH_UART_IRQ_PRI,
- bt_uart_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_BLUETOOTH_UART_IRQ);

/* Drain the fifo */
while (uart_irq_rx_ready(h4_dev)) {
@@ -234,6 +231,8 @@ static int h4_open(void)
uart_fifo_read(h4_dev, &c, 1);
}

+ uart_irq_callback_set(h4_dev, bt_uart_isr);
+
uart_irq_rx_enable(h4_dev);

return 0;
diff --git a/drivers/bluetooth/h5.c b/drivers/bluetooth/h5.c
index 5a6a4ba..562b0e7 100644
--- a/drivers/bluetooth/h5.c
+++ b/drivers/bluetooth/h5.c
@@ -445,7 +445,7 @@ static void h5_process_complete_packet(uint8_t *hdr)
}
}

-void bt_uart_isr(void *unused)
+static void bt_uart_isr(struct device *unused)
{
static int remaining;
uint8_t byte;
@@ -748,10 +748,6 @@ static int h5_open(void)
uart_irq_rx_disable(h5_dev);
uart_irq_tx_disable(h5_dev);

- IRQ_CONNECT(CONFIG_BLUETOOTH_UART_IRQ, CONFIG_BLUETOOTH_UART_IRQ_PRI,
- bt_uart_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_BLUETOOTH_UART_IRQ);
-
/* Drain the fifo */
while (uart_irq_rx_ready(h5_dev)) {
unsigned char c;
@@ -759,6 +755,8 @@ static int h5_open(void)
uart_fifo_read(h5_dev, &c, 1);
}

+ uart_irq_callback_set(h5_dev, bt_uart_isr);
+
h5_init();

uart_irq_rx_enable(h5_dev);
diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig
index c8dc686..0638f70 100644
--- a/drivers/console/Kconfig
+++ b/drivers/console/Kconfig
@@ -73,20 +73,6 @@ config UART_CONSOLE_ON_DEV_NAME
This option specifies the name of UART device to be used for
UART console.

-config UART_CONSOLE_IRQ
- int "IRQ of UART Device for UART Console"
- depends on UART_CONSOLE
- help
- This option specifies the IRQ of UART device to be used for
- UART console.
-
-config UART_CONSOLE_IRQ_PRI
- int "IRQ of UART Device for UART Console"
- depends on UART_CONSOLE
- help
- This option specifies the IRQ priorityof UART device to be
- used for UART console.
-
config UART_CONSOLE_PRIORITY
int
prompt "Init priority"
@@ -160,18 +146,4 @@ config UART_PIPE_ON_DEV_NAME
This option specifies the name of UART device to be used
for pipe UART.

-config UART_PIPE_IRQ
- int "IRQ for pipe UART"
- depends on UART_PIPE
- help
- This option specifies the IRQ of UART device to be used
- for pipe UART.
-
-config UART_PIPE_IRQ_PRI
- int "IRQ Priority for pipe UART"
- depends on UART_PIPE
- help
- This option specifies the IRQ priority of UART device
- to be used for pipe UART.
-
endif
diff --git a/drivers/console/uart_console.c b/drivers/console/uart_console.c
index 762b7aa..72c5631 100644
--- a/drivers/console/uart_console.c
+++ b/drivers/console/uart_console.c
@@ -278,7 +278,7 @@ ansi_cmd:
atomic_clear_bit(&esc_state, ESC_ANSI);
}

-void uart_console_isr(void *unused)
+void uart_console_isr(struct device *unused)
{
ARG_UNUSED(unused);

@@ -373,9 +373,8 @@ static void console_input_init(void)

uart_irq_rx_disable(uart_console_dev);
uart_irq_tx_disable(uart_console_dev);
- IRQ_CONNECT(CONFIG_UART_CONSOLE_IRQ, CONFIG_UART_CONSOLE_IRQ_PRI,
- uart_console_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_UART_CONSOLE_IRQ);
+
+ uart_irq_callback_set(uart_console_dev, uart_console_isr);

/* Drain the fifo */
while (uart_irq_rx_ready(uart_console_dev)) {
diff --git a/drivers/console/uart_pipe.c b/drivers/console/uart_pipe.c
index f56f9b1..c8c89ae 100644
--- a/drivers/console/uart_pipe.c
+++ b/drivers/console/uart_pipe.c
@@ -36,7 +36,7 @@ static size_t recv_buf_len;
static uart_pipe_recv_cb app_cb;
static size_t recv_off;

-void uart_pipe_isr(void *unused)
+static void uart_pipe_isr(struct device *unused)
{
ARG_UNUSED(unused);

@@ -77,10 +77,6 @@ static void uart_pipe_setup(struct device *uart)
uart_irq_rx_disable(uart);
uart_irq_tx_disable(uart);

- IRQ_CONNECT(CONFIG_UART_PIPE_IRQ, CONFIG_UART_PIPE_IRQ_PRI,
- uart_pipe_isr, 0, UART_IRQ_FLAGS);
- irq_enable(CONFIG_UART_PIPE_IRQ);
-
/* Drain the fifo */
while (uart_irq_rx_ready(uart)) {
unsigned char c;
@@ -88,6 +84,8 @@ static void uart_pipe_setup(struct device *uart)
uart_fifo_read(uart, &c, 1);
}

+ uart_irq_callback_set(uart, uart_pipe_isr);
+
uart_irq_rx_enable(uart);
}

diff --git a/drivers/serial/uart_k20.c b/drivers/serial/uart_k20.c
index 3f0985e..5c261f0 100644
--- a/drivers/serial/uart_k20.c
+++ b/drivers/serial/uart_k20.c
@@ -31,6 +31,7 @@
#include <toolchain.h>
#include <sections.h>

+#include "uart_k20.h"
#include "uart_k20_priv.h"

/* convenience defines */
@@ -45,6 +46,10 @@
/* Device data structure */
struct uart_k20_dev_data_t {
uint32_t baud_rate; /* Baud rate */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_callback_t cb; /**< Callback function pointer */
+#endif
};

static struct uart_driver_api uart_k20_driver_api;
@@ -90,6 +95,10 @@ static int uart_k20_init(struct device *dev)
/* restore interrupt state */
irq_unlock(old_level);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ dev_cfg->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_k20_driver_api;

return DEV_OK;
@@ -339,6 +348,41 @@ static int uart_k20_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_k20_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_k20_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+void uart_k20_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_k20_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */


@@ -360,6 +404,7 @@ static struct uart_driver_api uart_k20_driver_api = {
.irq_err_disable = uart_k20_irq_err_disable,
.irq_is_pending = uart_k20_irq_is_pending,
.irq_update = uart_k20_irq_update,
+ .irq_callback_set = uart_k20_irq_callback_set,

#endif
};
@@ -367,9 +412,17 @@ static struct uart_driver_api uart_k20_driver_api = {

#ifdef CONFIG_UART_K20_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_0 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_0_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_0 = {
@@ -380,13 +433,32 @@ DEVICE_INIT(uart_k20_0, CONFIG_UART_K20_PORT_0_NAME, &uart_k20_init,
&uart_k20_dev_data_0, &uart_k20_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_0_IRQ,
+ CONFIG_UART_K20_PORT_0_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_0 */

#ifdef CONFIG_UART_K20_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_1 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_1_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_1 = {
@@ -397,13 +469,32 @@ DEVICE_INIT(uart_k20_1, CONFIG_UART_K20_PORT_1_NAME, &uart_k20_init,
&uart_k20_dev_data_1, &uart_k20_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_1_IRQ,
+ CONFIG_UART_K20_PORT_1_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_1 */

#ifdef CONFIG_UART_K20_PORT_2

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_2 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_2_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_2_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_2,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_2 = {
@@ -414,13 +505,32 @@ DEVICE_INIT(uart_k20_2, CONFIG_UART_K20_PORT_2_NAME, &uart_k20_init,
&uart_k20_dev_data_2, &uart_k20_dev_cfg_2,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_2_IRQ,
+ CONFIG_UART_K20_PORT_2_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_2),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_2_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_2 */

#ifdef CONFIG_UART_K20_PORT_3

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_3(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_3 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_3_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_3_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_3,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_3 = {
@@ -431,13 +541,32 @@ DEVICE_INIT(uart_k20_3, CONFIG_UART_K20_PORT_3_NAME, &uart_k20_init,
&uart_k20_dev_data_3, &uart_k20_dev_cfg_3,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_3(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_3_IRQ,
+ CONFIG_UART_K20_PORT_3_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_3),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_3_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_3 */

#ifdef CONFIG_UART_K20_PORT_4

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_4(struct device *port);
+#endif
+
static struct uart_device_config uart_k20_dev_cfg_4 = {
.base = (uint8_t *)CONFIG_UART_K20_PORT_4_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_K20_PORT_4_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_4,
+#endif
};

static struct uart_k20_dev_data_t uart_k20_dev_data_4 = {
@@ -448,4 +577,15 @@ DEVICE_INIT(uart_k20_4, CONFIG_UART_K20_PORT_4_NAME, &uart_k20_init,
&uart_k20_dev_data_4, &uart_k20_dev_cfg_4,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_4(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_K20_PORT_4_IRQ,
+ CONFIG_UART_K20_PORT_4_IRQ_PRI,
+ uart_k20_isr, DEVICE_GET(uart_k20_4),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_K20_PORT_4_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_K20_PORT_4 */
diff --git a/drivers/serial/uart_k20.h b/drivers/serial/uart_k20.h
new file mode 100644
index 0000000..ca92859
--- /dev/null
+++ b/drivers/serial/uart_k20.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file UART header file for the K20 family of microprocessors..
+ */
+
+#ifndef _UART_K20_H_
+#define _UART_K20_H_
+
+void uart_k20_isr(void *arg);
+
+#endif /* _UART_K20_H_ */
diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c
index 543f7a0..f6b0b2e 100644
--- a/drivers/serial/uart_ns16550.c
+++ b/drivers/serial/uart_ns16550.c
@@ -210,6 +210,7 @@ struct uart_ns16550_dev_data_t {

#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uint8_t iir_cache; /**< cache of IIR since it clears when read */
+ uart_irq_callback_t cb; /**< Callback function pointer */
#endif

#ifdef CONFIG_UART_NS16550_DLF
@@ -336,6 +337,10 @@ static int uart_ns16550_init(struct device *dev)

irq_unlock(old_level);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ DEV_CFG(dev)->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_ns16550_driver_api;

return DEV_OK;
@@ -576,6 +581,41 @@ static int uart_ns16550_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_ns16550_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+static void uart_ns16550_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */

#ifdef CONFIG_UART_NS16550_LINE_CTRL
@@ -671,6 +711,7 @@ static struct uart_driver_api uart_ns16550_driver_api = {
.irq_err_disable = uart_ns16550_irq_err_disable,
.irq_is_pending = uart_ns16550_irq_is_pending,
.irq_update = uart_ns16550_irq_update,
+ .irq_callback_set = uart_ns16550_irq_callback_set,

#endif

@@ -685,6 +726,10 @@ static struct uart_driver_api uart_ns16550_driver_api = {

#ifdef CONFIG_UART_NS16550_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
struct uart_device_config uart_ns16550_dev_cfg_0 = {
.port = CONFIG_UART_NS16550_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_NS16550_PORT_0_CLK_FREQ,
@@ -698,6 +743,10 @@ struct uart_device_config uart_ns16550_dev_cfg_0 = {
.pci_dev.function = CONFIG_UART_NS16550_PORT_0_PCI_FUNC,
.pci_dev.bar = CONFIG_UART_NS16550_PORT_0_PCI_BAR,
#endif /* CONFIG_UART_NS16550_PORT_0_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_0 = {
@@ -713,10 +762,25 @@ DEVICE_INIT(uart_ns16550_0, CONFIG_UART_NS16550_PORT_0_NAME, &uart_ns16550_init,
&uart_ns16550_dev_data_0, &uart_ns16550_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_NS16550_PORT_0_IRQ,
+ CONFIG_UART_NS16550_PORT_0_IRQ_PRI,
+ uart_ns16550_isr, DEVICE_GET(uart_ns16550_0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_NS16550_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_NS16550_PORT_0 */

#ifdef CONFIG_UART_NS16550_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
struct uart_device_config uart_ns16550_dev_cfg_1 = {
.port = CONFIG_UART_NS16550_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_NS16550_PORT_1_CLK_FREQ,
@@ -730,6 +794,10 @@ struct uart_device_config uart_ns16550_dev_cfg_1 = {
.pci_dev.function = CONFIG_UART_NS16550_PORT_1_PCI_FUNC,
.pci_dev.bar = CONFIG_UART_NS16550_PORT_1_PCI_BAR,
#endif /* CONFIG_UART_NS16550_PORT_1_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_1 = {
@@ -745,4 +813,15 @@ DEVICE_INIT(uart_ns16550_1, CONFIG_UART_NS16550_PORT_1_NAME, &uart_ns16550_init,
&uart_ns16550_dev_data_1, &uart_ns16550_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_NS16550_PORT_1_IRQ,
+ CONFIG_UART_NS16550_PORT_1_IRQ_PRI,
+ uart_ns16550_isr, DEVICE_GET(uart_ns16550_1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_NS16550_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_NS16550_PORT_1 */
diff --git a/drivers/serial/uart_stellaris.c b/drivers/serial/uart_stellaris.c
index 3a6ea16..eaaa10e 100644
--- a/drivers/serial/uart_stellaris.c
+++ b/drivers/serial/uart_stellaris.c
@@ -34,6 +34,8 @@
#include <uart.h>
#include <sections.h>

+#include "uart_stellaris.h"
+
/* definitions */

/* Stellaris UART module */
@@ -76,6 +78,10 @@ struct _uart {
/* Device data structure */
struct uart_stellaris_dev_data_t {
uint32_t baud_rate; /* Baud rate */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_callback_t cb; /**< Callback function pointer */
+#endif
};

/* convenience defines */
@@ -271,6 +277,10 @@ static int uart_stellaris_init(struct device *dev)
line_control_defaults_set(dev);
enable(dev);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ DEV_CFG(dev)->irq_config_func(dev);
+#endif
+
dev->driver_api = &uart_stellaris_driver_api;

return DEV_OK;
@@ -565,6 +575,41 @@ static int uart_stellaris_irq_update(struct device *dev)
return 1;
}

+/**
+ * @brief Set the callback function pointer for IRQ.
+ *
+ * @param dev UART device struct
+ * @param cb Callback function pointer.
+ *
+ * @return N/A
+ */
+static void uart_stellaris_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_stellaris_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ dev_data->cb = cb;
+}
+
+/**
+ * @brief Interrupt service routine.
+ *
+ * This simply calls the callback function, if one exists.
+ *
+ * @param arg Argument to ISR.
+ *
+ * @return N/A
+ */
+void uart_stellaris_isr(void *arg)
+{
+ struct device *dev = arg;
+ struct uart_stellaris_dev_data_t * const dev_data = DEV_DATA(dev);
+
+ if (dev_data->cb) {
+ dev_data->cb(dev);
+ }
+}
+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */


@@ -586,6 +631,7 @@ static struct uart_driver_api uart_stellaris_driver_api = {
.irq_err_disable = uart_stellaris_irq_err_disable,
.irq_is_pending = uart_stellaris_irq_is_pending,
.irq_update = uart_stellaris_irq_update,
+ .irq_callback_set = uart_stellaris_irq_callback_set,

#endif
};
@@ -593,9 +639,17 @@ static struct uart_driver_api uart_stellaris_driver_api = {

#ifdef CONFIG_UART_STELLARIS_PORT_0

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_0 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_0_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_0_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_0,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_0 = {
@@ -606,13 +660,32 @@ DEVICE_INIT(uart_stellaris0, CONFIG_UART_STELLARIS_PORT_0_NAME, &uart_stellaris_
&uart_stellaris_dev_data_0, &uart_stellaris_dev_cfg_0,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_0(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_0_IRQ,
+ CONFIG_UART_STELLARIS_PORT_0_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris0),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_0_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_0 */

#ifdef CONFIG_UART_STELLARIS_PORT_1

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_1 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_1_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_1_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_1,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_1 = {
@@ -623,13 +696,32 @@ DEVICE_INIT(uart_stellaris1, CONFIG_UART_STELLARIS_PORT_1_NAME, &uart_stellaris_
&uart_stellaris_dev_data_1, &uart_stellaris_dev_cfg_1,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_1(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_1_IRQ,
+ CONFIG_UART_STELLARIS_PORT_1_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris1),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_1_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_1 */

#ifdef CONFIG_UART_STELLARIS_PORT_2

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *port);
+#endif
+
static struct uart_device_config uart_stellaris_dev_cfg_2 = {
.base = (uint8_t *)CONFIG_UART_STELLARIS_PORT_2_BASE_ADDR,
.sys_clk_freq = CONFIG_UART_STELLARIS_PORT_2_CLK_FREQ,
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ .irq_config_func = irq_config_func_2,
+#endif
};

static struct uart_stellaris_dev_data_t uart_stellaris_dev_data_2 = {
@@ -640,4 +732,15 @@ DEVICE_INIT(uart_stellaris2, CONFIG_UART_STELLARIS_PORT_2_NAME, &uart_stellaris_
&uart_stellaris_dev_data_2, &uart_stellaris_dev_cfg_2,
PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+static void irq_config_func_2(struct device *dev)
+{
+ IRQ_CONNECT(CONFIG_UART_STELLARIS_PORT_2_IRQ,
+ CONFIG_UART_STELLARIS_PORT_2_IRQ_PRI,
+ uart_stellaris_isr, DEVICE_GET(uart_stellaris2),
+ UART_IRQ_FLAGS);
+ irq_enable(CONFIG_UART_STELLARIS_PORT_2_IRQ);
+}
+#endif
+
#endif /* CONFIG_UART_STELLARIS_PORT_2 */
diff --git a/drivers/serial/uart_stellaris.h b/drivers/serial/uart_stellaris.h
new file mode 100644
index 0000000..4a14ef3
--- /dev/null
+++ b/drivers/serial/uart_stellaris.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file Header file for Stellaris UART.
+ */
+
+#ifndef _UART_STELLARIS_H_
+#define _UART_STELLARIS_H_
+
+void uart_console_isr(void *arg);
+
+#endif /* _UART_STELLARIS_H_ */
diff --git a/include/drivers/console/uart_console.h b/include/drivers/console/uart_console.h
index 4634e33..963e8af 100644
--- a/include/drivers/console/uart_console.h
+++ b/include/drivers/console/uart_console.h
@@ -46,8 +46,6 @@ struct uart_console_input {
*/
void uart_register_input(struct nano_fifo *avail, struct nano_fifo *lines);

-void uart_console_isr(void *unused);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/drivers/console/uart_pipe.h b/include/drivers/console/uart_pipe.h
index 3b7594a..2391bbd 100644
--- a/include/drivers/console/uart_pipe.h
+++ b/include/drivers/console/uart_pipe.h
@@ -62,15 +62,6 @@ void uart_pipe_register(uint8_t *buf, size_t len, uart_pipe_recv_cb cb);
*/
int uart_pipe_send(const uint8_t *data, int len);

-/** @brief Simple UART interrupt handler.
- *
- * This function is called from an interrupt and should not be called by
- * an application directly.
- *
- * @param unused unused
- */
-void uart_pipe_isr(void *unused);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/uart.h b/include/uart.h
index 66e5123..cba33c3 100644
--- a/include/uart.h
+++ b/include/uart.h
@@ -71,6 +71,16 @@ extern "C" {
*/
#define UART_ERROR_BREAK (1 << 3)

+/**
+ * @brief Define the application callback function signature for UART.
+ *
+ * @param port Device struct for the UART device.
+ */
+typedef void (*uart_irq_callback_t)(struct device *port);
+
+/* For configuring IRQ on each individual UART device. Internal use only. */
+typedef void (*uart_irq_config_func_t)(struct device *port);
+
/** @brief UART device configuration.*/
struct uart_device_config {
/**
@@ -90,6 +100,10 @@ struct uart_device_config {
#ifdef CONFIG_PCI
struct pci_dev_info pci_dev;
#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_config_func_t irq_config_func;
+#endif
};

/** @brief Driver API structure. */
@@ -145,6 +159,9 @@ struct uart_driver_api {
/** Interrupt driven input hook function */
int (*irq_input_hook)(struct device *dev, uint8_t byte);

+ /** Set the callback function */
+ void (*irq_callback_set)(struct device *dev, uart_irq_callback_t cb);
+
#endif

#ifdef CONFIG_UART_LINE_CTRL
@@ -516,6 +533,30 @@ static inline void uart_irq_input_hook_set(struct device *dev,
}
}

+
+/**
+ * @brief Set the IRQ callback function pointer.
+ *
+ * This sets up the callback for IRQ. When an IRQ is triggered,
+ * the specified function will be called.
+ *
+ * @param dev UART device structure.
+ * @param cb Pointer to the callback function.
+ *
+ * @return N/A
+ */
+static inline void uart_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
+{
+ struct uart_driver_api *api;
+
+ api = (struct uart_driver_api *)dev->driver_api;
+
+ if ((api != NULL) && (api->irq_callback_set != NULL)) {
+ api->irq_callback_set(dev, cb);
+ }
+}
+
#endif

#ifdef CONFIG_UART_LINE_CTRL


Johan Hedberg
 

Hi Daniel,

On Mon, Feb 29, 2016, Daniel Leung wrote:
arch/arc/soc/quark_se_ss/Kconfig | 4 -
arch/arm/soc/atmel_sam3/Kconfig | 4 -
arch/arm/soc/atmel_sam3/irq_vector_table.c | 16 ---
arch/arm/soc/fsl_frdm_k64f/Kconfig | 8 --
arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c | 51 +++++++---
arch/arm/soc/ti_lm3s6965/Kconfig | 20 ++--
arch/arm/soc/ti_lm3s6965/irq_vector_table.c | 39 ++++---
arch/x86/soc/atom/Kconfig | 12 ---
arch/x86/soc/ia32/Kconfig | 12 ---
arch/x86/soc/quark_d2000/Kconfig | 12 ---
arch/x86/soc/quark_se/Kconfig | 8 --
arch/x86/soc/quark_x1000/Kconfig | 8 --
boards/arduino_101/Kconfig | 4 -
drivers/bluetooth/Kconfig | 14 ---
drivers/bluetooth/h4.c | 7 +-
drivers/bluetooth/h5.c | 8 +-
drivers/console/Kconfig | 28 ------
drivers/console/uart_console.c | 7 +-
drivers/console/uart_pipe.c | 8 +-
drivers/serial/uart_k20.c | 140 ++++++++++++++++++++++++++
drivers/serial/uart_k20.h | 26 +++++
drivers/serial/uart_ns16550.c | 79 +++++++++++++++
drivers/serial/uart_stellaris.c | 103 +++++++++++++++++++
drivers/serial/uart_stellaris.h | 26 +++++
include/drivers/console/uart_console.h | 2 -
include/drivers/console/uart_pipe.h | 9 --
include/uart.h | 41 ++++++++
It seems you've missed at least drivers/nble/uart.c that uses both
IRQ_CONNECT and irq_enable. Otherwise the change looks fine to me.

Johan


Daniel Leung <daniel.leung@...>
 

On Tue, Mar 01, 2016 at 05:14:12PM +0200, Johan Hedberg wrote:
Hi Daniel,

On Mon, Feb 29, 2016, Daniel Leung wrote:
arch/arc/soc/quark_se_ss/Kconfig | 4 -
arch/arm/soc/atmel_sam3/Kconfig | 4 -
arch/arm/soc/atmel_sam3/irq_vector_table.c | 16 ---
arch/arm/soc/fsl_frdm_k64f/Kconfig | 8 --
arch/arm/soc/fsl_frdm_k64f/irq_vector_table.c | 51 +++++++---
arch/arm/soc/ti_lm3s6965/Kconfig | 20 ++--
arch/arm/soc/ti_lm3s6965/irq_vector_table.c | 39 ++++---
arch/x86/soc/atom/Kconfig | 12 ---
arch/x86/soc/ia32/Kconfig | 12 ---
arch/x86/soc/quark_d2000/Kconfig | 12 ---
arch/x86/soc/quark_se/Kconfig | 8 --
arch/x86/soc/quark_x1000/Kconfig | 8 --
boards/arduino_101/Kconfig | 4 -
drivers/bluetooth/Kconfig | 14 ---
drivers/bluetooth/h4.c | 7 +-
drivers/bluetooth/h5.c | 8 +-
drivers/console/Kconfig | 28 ------
drivers/console/uart_console.c | 7 +-
drivers/console/uart_pipe.c | 8 +-
drivers/serial/uart_k20.c | 140 ++++++++++++++++++++++++++
drivers/serial/uart_k20.h | 26 +++++
drivers/serial/uart_ns16550.c | 79 +++++++++++++++
drivers/serial/uart_stellaris.c | 103 +++++++++++++++++++
drivers/serial/uart_stellaris.h | 26 +++++
include/drivers/console/uart_console.h | 2 -
include/drivers/console/uart_pipe.h | 9 --
include/uart.h | 41 ++++++++
It seems you've missed at least drivers/nble/uart.c that uses both
IRQ_CONNECT and irq_enable. Otherwise the change looks fine to me.
Thanks for letting me know about this. I will modify and re-submit.

If anyone notices anything missing, please let me know.


-----
Daniel Leung


Tomasz Bursztyka
 

Hi Daniel,

I am a bit late on that one. I fully agree on such addition.
1 comment below:

+/**
+ * @brief Define the application callback function signature for UART.
+ *
+ * @param port Device struct for the UART device.
+ */
+typedef void (*uart_irq_callback_t)(struct device *port);
+
Could be wise to add a void *user_data private pointer through the callback.
It's something we are missing not only here (gpio etc...)

+/* For configuring IRQ on each individual UART device. Internal use only. */
+typedef void (*uart_irq_config_func_t)(struct device *port);
+
/** @brief UART device configuration.*/
struct uart_device_config {
/**
@@ -90,6 +100,10 @@ struct uart_device_config {
#ifdef CONFIG_PCI
struct pci_dev_info pci_dev;
#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_config_func_t irq_config_func;
+#endif
};

/** @brief Driver API structure. */
@@ -145,6 +159,9 @@ struct uart_driver_api {
/** Interrupt driven input hook function */
int (*irq_input_hook)(struct device *dev, uint8_t byte);

+ /** Set the callback function */
+ void (*irq_callback_set)(struct device *dev, uart_irq_callback_t cb);
+
#endif

#ifdef CONFIG_UART_LINE_CTRL
@@ -516,6 +533,30 @@ static inline void uart_irq_input_hook_set(struct device *dev,
}
}

+
+/**
+ * @brief Set the IRQ callback function pointer.
+ *
+ * This sets up the callback for IRQ. When an IRQ is triggered,
+ * the specified function will be called.
+ *
+ * @param dev UART device structure.
+ * @param cb Pointer to the callback function.
+ *
+ * @return N/A
+ */
+static inline void uart_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
so it would have a void *user_data parameter as well

+{
+ struct uart_driver_api *api;
+
+ api = (struct uart_driver_api *)dev->driver_api;
+
+ if ((api != NULL) && (api->irq_callback_set != NULL)) {
I guess we do this api != NULL check because of the
UART_INTERRUPT_DRIVEN option.
I guess at some point we will be only interrupt driven anyway.


Tomasz


Daniel Leung <daniel.leung@...>
 

On Thu, Mar 03, 2016 at 05:07:31PM +0100, Tomasz Bursztyka wrote:
Hi Daniel,

I am a bit late on that one. I fully agree on such addition.
1 comment below:

+/**
+ * @brief Define the application callback function signature for UART.
+ *
+ * @param port Device struct for the UART device.
+ */
+typedef void (*uart_irq_callback_t)(struct device *port);
+
Could be wise to add a void *user_data private pointer through the callback.
It's something we are missing not only here (gpio etc...)
Do you have a particular use case in mind, w.r.t. UART, that requires
user data? At this point, the patch is to simply move the IRQ setup
code into the UART drivers. This is not a callback in generic terms,
but just a an ISR calling another ISR. Since the first ISR does not have
any additional user data, the second ISR should not be dependent on
having additional information.

+/* For configuring IRQ on each individual UART device. Internal use only. */
+typedef void (*uart_irq_config_func_t)(struct device *port);
+
/** @brief UART device configuration.*/
struct uart_device_config {
/**
@@ -90,6 +100,10 @@ struct uart_device_config {
#ifdef CONFIG_PCI
struct pci_dev_info pci_dev;
#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_UART_INTERRUPT_DRIVEN
+ uart_irq_config_func_t irq_config_func;
+#endif
};

/** @brief Driver API structure. */
@@ -145,6 +159,9 @@ struct uart_driver_api {
/** Interrupt driven input hook function */
int (*irq_input_hook)(struct device *dev, uint8_t byte);

+ /** Set the callback function */
+ void (*irq_callback_set)(struct device *dev, uart_irq_callback_t cb);
+
#endif

#ifdef CONFIG_UART_LINE_CTRL
@@ -516,6 +533,30 @@ static inline void uart_irq_input_hook_set(struct device *dev,
}
}

+
+/**
+ * @brief Set the IRQ callback function pointer.
+ *
+ * This sets up the callback for IRQ. When an IRQ is triggered,
+ * the specified function will be called.
+ *
+ * @param dev UART device structure.
+ * @param cb Pointer to the callback function.
+ *
+ * @return N/A
+ */
+static inline void uart_irq_callback_set(struct device *dev,
+ uart_irq_callback_t cb)
so it would have a void *user_data parameter as well

+{
+ struct uart_driver_api *api;
+
+ api = (struct uart_driver_api *)dev->driver_api;
+
+ if ((api != NULL) && (api->irq_callback_set != NULL)) {
I guess we do this api != NULL check because of the
UART_INTERRUPT_DRIVEN option.
I guess at some point we will be only interrupt driven anyway.
The UART drivers are done in a way where driver_api is NULL
if the driver init fails, hence the (api != NULL) check.


-----
Daniel Leung