rendered paste bodyIndex: target/linux/danube/files/drivers/serial/danube_asc.c
===================================================================
--- target/linux/danube/files/drivers/serial/danube_asc.c (revision 138)
+++ target/linux/danube/files/drivers/serial/danube_asc.c (working copy)
@@ -48,8 +48,8 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
-#include <asm/danube/danube.h>
-#include <asm/danube/irq.h>
+#include <asm/danube/danube_new.h>
+#include <asm/danube/danube_irq.h>
#include <asm/danube/serial.h>
#define PORT_DANUBEASC 111
@@ -65,11 +65,6 @@
#define SERIAL_DANUBEASC_MINOR 64
#define SERIAL_DANUBEASC_NR UART_NR
-#define SET_BIT(reg, mask) *reg |= (mask)
-#define CLEAR_BIT(reg, mask) *reg &= (~mask)
-#define SET_BITFIELD(reg, mask, off, val) \
- {*reg &= (~mask); *reg |= (val << off);}
-
static void danubeasc_tx_chars(struct uart_port *port);
extern void prom_printf(const char * fmt, ...);
static struct uart_port danubeasc_ports[UART_NR];
@@ -77,13 +72,15 @@
static unsigned int uartclk = 0;
extern unsigned int danube_get_fpi_hz(void);
-static void danubeasc_stop_tx(struct uart_port *port)
+static void
+danubeasc_stop_tx (struct uart_port *port)
{
/* fifo underrun shuts up after firing once */
return;
}
-static void danubeasc_start_tx(struct uart_port *port)
+static void
+danubeasc_start_tx (struct uart_port *port)
{
unsigned long flags;
@@ -94,30 +91,32 @@
return;
}
-static void danubeasc_stop_rx(struct uart_port *port)
+static void
+danubeasc_stop_rx (struct uart_port *port)
{
/* clear the RX enable bit */
- *DANUBE_ASC1_WHBSTATE = ASCWHBSTATE_CLRREN;
+ writel(ASCWHBSTATE_CLRREN, DANUBE_ASC1_WHBSTATE);
}
-static void danubeasc_enable_ms(struct uart_port *port)
+static void
+danubeasc_enable_ms (struct uart_port *port)
{
/* no modem signals */
return;
}
static void
-danubeasc_rx_chars(struct uart_port *port)
+danubeasc_rx_chars (struct uart_port *port)
{
struct tty_struct *tty = port->info->tty;
unsigned int ch = 0, rsr = 0, fifocnt;
- fifocnt = *DANUBE_ASC1_FSTAT & ASCFSTAT_RXFFLMASK;
+ fifocnt = readl(DANUBE_ASC1_FSTAT) & ASCFSTAT_RXFFLMASK;
while (fifocnt--)
{
u8 flag = TTY_NORMAL;
- ch = *DANUBE_ASC1_RBUF;
- rsr = (*DANUBE_ASC1_STATE & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
+ ch = readl(DANUBE_ASC1_RBUF);
+ rsr = (readl(DANUBE_ASC1_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
tty_flip_buffer_push(tty);
port->icount.rx++;
@@ -128,14 +127,14 @@
if (rsr & ASCSTATE_ANY) {
if (rsr & ASCSTATE_PE) {
port->icount.parity++;
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRPE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRPE, DANUBE_ASC1_WHBSTATE);
} else if (rsr & ASCSTATE_FE) {
port->icount.frame++;
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRFE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRFE, DANUBE_ASC1_WHBSTATE);
}
if (rsr & ASCSTATE_ROE) {
port->icount.overrun++;
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRROE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRROE, DANUBE_ASC1_WHBSTATE);
}
rsr &= port->read_status_mask;
@@ -164,7 +163,8 @@
}
-static void danubeasc_tx_chars(struct uart_port *port)
+static void
+danubeasc_tx_chars (struct uart_port *port)
{
struct circ_buf *xmit = &port->info->xmit;
@@ -173,11 +173,11 @@
return;
}
- while(((*DANUBE_ASC1_FSTAT & ASCFSTAT_TXFFLMASK)
+ while(((readl(DANUBE_ASC1_FSTAT) & ASCFSTAT_TXFFLMASK)
>> ASCFSTAT_TXFFLOFF) != DANUBEASC_TXFIFO_FULL)
{
if (port->x_char) {
- *DANUBE_ASC1_TBUF = port->x_char;
+ writel(port->x_char, DANUBE_ASC1_TBUF);
port->icount.tx++;
port->x_char = 0;
continue;
@@ -186,7 +186,7 @@
if (uart_circ_empty(xmit))
break;
- *DANUBE_ASC1_TBUF = port->info->xmit.buf[port->info->xmit.tail];
+ writel(port->info->xmit.buf[port->info->xmit.tail], DANUBE_ASC1_TBUF);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}
@@ -194,103 +194,89 @@
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
}
-extern void
-mask_and_ack_danube_irq (unsigned int irq_nr);
-static irqreturn_t danubeasc_tx_int(int irq, void *port)
+static irqreturn_t
+danubeasc_tx_int (int irq, void *port)
{
- *(DANUBE_ASC1_IRNCR) = ASC_IRNCR_TIR;
- //*(DANUBE_ASC1_IRNICR) = ASC_IRNCR_TIR;
+ writel(ASC_IRNCR_TIR, DANUBE_ASC1_IRNCR);
danubeasc_start_tx(port);
mask_and_ack_danube_irq(irq);
+
return IRQ_HANDLED;
}
-static irqreturn_t danubeasc_er_int(int irq, void *port)
+static irqreturn_t
+danubeasc_er_int (int irq, void *port)
{
+ //TODO all in one ?
/* clear any pending interrupts */
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRPE);
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRFE);
- SET_BIT (DANUBE_ASC1_WHBSTATE, ASCWHBSTATE_CLRROE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRPE, DANUBE_ASC1_WHBSTATE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRFE, DANUBE_ASC1_WHBSTATE);
+ writel(readl(DANUBE_ASC1_WHBSTATE) | ASCWHBSTATE_CLRROE, DANUBE_ASC1_WHBSTATE);
return IRQ_HANDLED;
}
-static irqreturn_t danubeasc_rx_int(int irq, void *port)
+static irqreturn_t
+danubeasc_rx_int (int irq, void *port)
{
- //printk("----%s:%s[%d] %d %d\n", __FILE__, __func__, __LINE__, ASC_IRNCR_RIR, * ((u32*)(DANUBE_ASC1_IRNCR)));
- *(DANUBE_ASC1_IRNCR) = ASC_IRNCR_RIR;
-// writel(ASC_IRNCR_RIR, ((u32*)(DANUBE_ASC1_IRNCR)));
-// printk(" %s:%s[%d] %d %d\n", __FILE__, __func__, __LINE__, ASC_IRNCR_RIR, * ((u32*)(DANUBE_ASC1_IRNCR)));
-// printk(" %s:%s[%d] %d %d\n", __FILE__, __func__, __LINE__, ASC_IRNCR_RIR, * ((u32*)(DANUBE_ASC1_IRNICR)));
-//*(DANUBE_ASC1_IRNCR) = ASC_IRNCR_RIR;
+ writel(ASC_IRNCR_RIR, DANUBE_ASC1_IRNCR);
danubeasc_rx_chars((struct uart_port *) port);
mask_and_ack_danube_irq(irq);
+
return IRQ_HANDLED;
}
-static u_int danubeasc_tx_empty(struct uart_port *port)
+static unsigned int
+danubeasc_tx_empty (struct uart_port *port)
{
int status;
- /*
- * FSTAT tells exactly how many bytes are in the FIFO.
- * The question is whether we really need to wait for all
- * 16 bytes to be transmitted before reporting that the
- * transmitter is empty.
- */
- status = *DANUBE_ASC1_FSTAT & ASCFSTAT_TXFFLMASK;
+ status = readl(DANUBE_ASC1_FSTAT) & ASCFSTAT_TXFFLMASK;
return status ? 0 : TIOCSER_TEMT;
}
-static u_int danubeasc_get_mctrl(struct uart_port *port)
+static unsigned int
+danubeasc_get_mctrl (struct uart_port *port)
{
- /* no modem control signals - the readme says to pretend all are set */
return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
}
-static void danubeasc_set_mctrl(struct uart_port *port, u_int mctrl)
+static void
+danubeasc_set_mctrl (struct uart_port *port, u_int mctrl)
{
- /* no modem control - just return */
return;
}
-static void danubeasc_break_ctl(struct uart_port *port, int break_state)
+static void
+danubeasc_break_ctl (struct uart_port *port, int break_state)
{
- /* no way to send a break */
return;
}
-static void danubeasc1_hw_init(void)
+static void
+danubeasc1_hw_init (void)
{
- u32 con;
/* this setup was probably already done in ROM/u-boot */
/* ASC and GPIO Port 1 bits 3 and 4 share the same pins
* TODO: GPIO pins
*/
- /* set up the CLC */
- CLEAR_BIT (DANUBE_ASC1_CLC, DANUBE_ASC1_CLC_DISS);
- SET_BITFIELD (DANUBE_ASC1_CLC, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 1);
- /* asynchronous mode */
- con = ASCCON_M_8ASYNC;
- /* set error signals - framing and overrun */
- //con |= ASCCON_FEN;
- //con |= ASCCON_TOEN;
- //con |= ASCCON_ROEN;
- /* choose the line - there's only one */
- *DANUBE_ASC1_PISEL = 0;
- *DANUBE_ASC1_TXFCON =
- (((DANUBEASC_TXFIFO_FL << ASCTXFCON_TXFITLOFF) &
- ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU);
- *DANUBE_ASC1_RXFCON =
- (((DANUBEASC_RXFIFO_FL << ASCRXFCON_RXFITLOFF) &
- ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU);
+ writel(readl(DANUBE_ASC1_CLC) & ~DANUBE_ASC1_CLC_DISS, DANUBE_ASC1_CLC);
+ writel((readl(DANUBE_ASC1_CLC) & ~ASCCLC_RMCMASK) | (ASCCLC_RMCOFFSET << 1), DANUBE_ASC1_CLC);
+ writel(0, DANUBE_ASC1_PISEL);
+ writel(((DANUBEASC_TXFIFO_FL << ASCTXFCON_TXFITLOFF) &
+ ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, DANUBE_ASC1_TXFCON);
+ writel(((DANUBEASC_RXFIFO_FL << ASCRXFCON_RXFITLOFF) &
+ ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, DANUBE_ASC1_RXFCON);
wmb ();
- SET_BIT (DANUBE_ASC1_CON, con);
+
+ /*TODO do we need framing and overrun here ? */
+ writel(readl(DANUBE_ASC1_CON) | ASCCON_M_8ASYNC /* | ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN */, DANUBE_ASC1_CON);
}
-static int danubeasc_startup(struct uart_port *port)
+static int
+danubeasc_startup (struct uart_port *port)
{
unsigned long flags;
int retval;
@@ -325,7 +311,7 @@
/* enable interrupt mask in peripheral */
/* TODO: */
- *DANUBE_ASC1_IRNREN = 0xf;
+ writel(0xf, DANUBE_ASC1_IRNREN);
local_irq_restore(flags);
@@ -337,10 +323,12 @@
err1:
free_irq(DANUBEASC1_RIR, port);
local_irq_restore(flags);
+
return retval;
}
-static void danubeasc_shutdown(struct uart_port *port)
+static void
+danubeasc_shutdown (struct uart_port *port)
{
free_irq(DANUBEASC1_RIR, port);
free_irq(DANUBEASC1_TIR, port);
@@ -348,14 +336,13 @@
/*
* disable the baudrate generator to disable the ASC
*/
- // TODO
- // *DANUBE_ASC1_CON = 0;
+ writel(0, DANUBE_ASC1_CON);
/* flush and then disable the fifos */
- SET_BIT (DANUBE_ASC1_RXFCON, ASCRXFCON_RXFFLU);
- CLEAR_BIT (DANUBE_ASC1_RXFCON, ASCRXFCON_RXFEN);
- SET_BIT (DANUBE_ASC1_TXFCON, ASCTXFCON_TXFFLU);
- CLEAR_BIT (DANUBE_ASC1_TXFCON, ASCTXFCON_TXFEN);
+ writel(readl(DANUBE_ASC1_RXFCON) | ASCRXFCON_RXFFLU, DANUBE_ASC1_RXFCON);
+ writel(readl(DANUBE_ASC1_RXFCON) & ~ASCRXFCON_RXFEN, DANUBE_ASC1_RXFCON);
+ writel(readl(DANUBE_ASC1_TXFCON) | ASCTXFCON_TXFFLU, DANUBE_ASC1_TXFCON);
+ writel(readl(DANUBE_ASC1_TXFCON) & ~ASCTXFCON_TXFEN, DANUBE_ASC1_TXFCON);
}
static void danubeasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old)
@@ -372,19 +359,20 @@
/* byte size and parity */
switch (cflag & CSIZE) {
- /* 7 bits are always with parity */
case CS7:
con = ASCCON_M_7ASYNC;
break;
- /* the ASC only suports 7 and 8 bits */
+
case CS5:
case CS6:
default:
con = ASCCON_M_8ASYNC;
break;
}
+
if (cflag & CSTOPB)
con |= ASCCON_STP;
+
if (cflag & PARENB) {
if (!(cflag & PARODD))
con &= ~ASCCON_ODD;
@@ -409,72 +397,63 @@
port->ignore_status_mask |= ASCSTATE_ROE;
}
- /*
- * Ignore all characters if CREAD is not set.
- */
if ((cflag & CREAD) == 0)
port->ignore_status_mask |= UART_DUMMY_UER_RX;
- /* set error signals - framing, parity and overrun */
- con |= ASCCON_FEN;
- con |= ASCCON_TOEN;
- /* enable the receiver */
- con |= ASCCON_ROEN;
+ /* set error signals - framing, parity and overrun, enable receiver */
+ con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
- /* block the IRQs */
local_irq_save(flags);
/* set up CON */
- SET_BIT (DANUBE_ASC1_CON, con);
+ writel(readl(DANUBE_ASC1_CON) | con, DANUBE_ASC1_CON);
/* Set baud rate - take a divider of 2 into account */
- baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
- quot = quot/2 - 1;
+ quot = quot / 2 - 1;
/* disable the baudrate generator */
- CLEAR_BIT (DANUBE_ASC1_CON, ASCCON_R);
+ writel(readl(DANUBE_ASC1_CON) & ~ASCCON_R, DANUBE_ASC1_CON);
+
/* make sure the fractional divider is off */
- CLEAR_BIT (DANUBE_ASC1_CON, ASCCON_FDE);
+ writel(readl(DANUBE_ASC1_CON) & ~ASCCON_FDE, DANUBE_ASC1_CON);
+
/* set up to use divisor of 2 */
- CLEAR_BIT (DANUBE_ASC1_CON, ASCCON_BRS);
+ writel(readl(DANUBE_ASC1_CON) & ~ASCCON_BRS, DANUBE_ASC1_CON);
+
/* now we can write the new baudrate into the register */
- *DANUBE_ASC1_BG = quot;
+ writel(quot, DANUBE_ASC1_BG);
/* turn the baudrate generator back on */
- SET_BIT (DANUBE_ASC1_CON, ASCCON_R);
+ writel(readl(DANUBE_ASC1_CON) | ASCCON_R, DANUBE_ASC1_CON);
/* enable rx */
- *DANUBE_ASC1_WHBSTATE = ASCWHBSTATE_SETREN;
+ writel(ASCWHBSTATE_SETREN, DANUBE_ASC1_WHBSTATE);
local_irq_restore(flags);
}
-static const char *danubeasc_type(struct uart_port *port)
+static const char*
+danubeasc_type (struct uart_port *port)
{
return port->type == PORT_DANUBEASC ? "DANUBEASC" : NULL;
}
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void danubeasc_release_port(struct uart_port *port)
+static void
+danubeasc_release_port (struct uart_port *port)
{
return;
}
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int danubeasc_request_port(struct uart_port *port)
+static int
+danubeasc_request_port (struct uart_port *port)
{
return 0;
}
-/*
- * Configure/autoconfigure the port.
- */
-static void danubeasc_config_port(struct uart_port *port, int flags)
+static void
+danubeasc_config_port (struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
port->type = PORT_DANUBEASC;
@@ -482,10 +461,8 @@
}
}
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int danubeasc_verify_port(struct uart_port *port, struct serial_struct *ser)
+static int
+danubeasc_verify_port (struct uart_port *port, struct serial_struct *ser)
{
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_DANUBEASC)
@@ -518,31 +495,33 @@
static struct uart_port danubeasc_ports[UART_NR] = {
{
- membase: (void *)DANUBE_ASC1,
- mapbase: DANUBE_ASC1,
+ membase: (void *)DANUBE_ASC1_BASE_ADDR,
+ mapbase: DANUBE_ASC1_BASE_ADDR,
iotype: SERIAL_IO_MEM,
- irq: DANUBEASC1_RIR, /* RIR */
- uartclk: 0, /* filled in dynamically */
+ irq: DANUBEASC1_RIR,
+ uartclk: 0,
fifosize: 16,
- unused: { DANUBEASC1_TIR, DANUBEASC1_EIR}, /* xmit/error/xmit-buffer-empty IRQ */
+ unused: {DANUBEASC1_TIR, DANUBEASC1_EIR},
type: PORT_DANUBEASC,
ops: &danubeasc_pops,
flags: ASYNC_BOOT_AUTOCONF,
},
};
-static void danubeasc_console_write(struct console *co, const char *s, u_int count)
+static void
+danubeasc_console_write (struct console *co, const char *s, u_int count)
{
- int i, fifocnt;
+ int i = 0, fifocnt;
unsigned long flags;
- local_irq_save(flags);
- for (i = 0; i < count;)
+ local_irq_save(flags);
+ // TODO add a for loop
+ while (i < count)
{
/* wait until the FIFO is not full */
do
{
- fifocnt = (*DANUBE_ASC1_FSTAT & ASCFSTAT_TXFFLMASK)
+ fifocnt = (readl(DANUBE_ASC1_FSTAT) & ASCFSTAT_TXFFLMASK)
>> ASCFSTAT_TXFFLOFF;
} while (fifocnt == DANUBEASC_TXFIFO_FULL);
@@ -553,91 +532,29 @@
if (s[i] == '\n')
{
- *DANUBE_ASC1_TBUF = '\r';
+ writel('\r', DANUBE_ASC1_TBUF);
do
{
- fifocnt = (*DANUBE_ASC1_FSTAT &
- ASCFSTAT_TXFFLMASK) >>
- ASCFSTAT_TXFFLOFF;
+ fifocnt = (readl(DANUBE_ASC1_FSTAT) & ASCFSTAT_TXFFLMASK)
+ >> ASCFSTAT_TXFFLOFF;
} while (fifocnt == DANUBEASC_TXFIFO_FULL);
}
- *DANUBE_ASC1_TBUF = s[i];
+ writel(s[i], DANUBE_ASC1_TBUF);
i++;
}
local_irq_restore(flags);
}
-/*
-TODO
-static void __init
-danubeasc_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
+static int __init
+danubeasc_console_setup (struct console *co, char *options)
{
- u_int lcr_h;
-
- lcr_h = *DANUBE_ASC1_CON;
- if (lcr_h & ASCCON_R) {
- u_int quot, div, fdiv, frac;
-
- *parity = 'n';
- if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNC ||
- (lcr_h & ASCCON_MODEMASK) == ASCCON_M_8ASYNC) {
- if (lcr_h & ASCCON_ODD)
- *parity = 'o';
- else
- *parity = 'e';
- }
-
- if ((lcr_h & ASCCON_MODEMASK) == ASCCON_M_7ASYNC)
- *bits = 7;
- else
- *bits = 8;
-
- quot = *DANUBE_ASC1_BG + 1;
-
- if (lcr_h & ASCCON_FDE)
- {
- div = 1;
- fdiv = *DANUBE_ASC1_FDV;
- if (fdiv == 0)
- fdiv = 512;
- frac = 512;
- }
- else
- {
- div = lcr_h & ASCCON_BRS ? 3 : 2;
- fdiv = frac = 1;
- }
-
- *baud = frac * (port->uartclk / (div * 512 * 16 * quot));
- if (*baud > 1100 && *baud < 2400)
- *baud = 1200;
- if (*baud > 2300 && *baud < 4800)
- *baud = 2400;
- if (*baud > 4700 && *baud < 9600)
- *baud = 4800;
- if (*baud > 9500 && *baud < 19200)
- *baud = 9600;
- if (*baud > 19000 && *baud < 38400)
- *baud = 19200;
- if (*baud > 38400 && *baud < 57600)
- *baud = 38400;
- if (*baud > 57600 && *baud < 115200)
- *baud = 57600;
- if (*baud > 115200 && *baud < 230400)
- *baud = 115200;
- }
-}
-*/
-static int __init danubeasc_console_setup(struct console *co, char *options)
-{
struct uart_port *port;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
- /* this assumes: CON.BRS = CON.FDE = 0 */
if (uartclk == 0)
uartclk = danube_get_fpi_hz();
co->index = 0;
@@ -663,7 +580,8 @@
data: &danubeasc_reg,
};
-static int __init danubeasc_console_init(void)
+static int __init
+danubeasc_console_init (void)
{
register_console(&danubeasc_console);
return 0;
@@ -672,7 +590,7 @@
static struct uart_driver danubeasc_reg = {
.owner = THIS_MODULE,
- .driver_name = "serial",
+ .driver_name = "serial",
.dev_name = "ttyS",
.major = TTY_MAJOR,
.minor = 64,
@@ -680,15 +598,19 @@
.cons = &danubeasc_console,
};
-static int __init danubeasc_init(void)
+static int __init
+danubeasc_init (void)
{
unsigned char res;
+
uart_register_driver(&danubeasc_reg);
res = uart_add_one_port(&danubeasc_reg, &danubeasc_ports[0]);
+
return res;
}
-static void __exit danubeasc_exit(void)
+static void __exit
+danubeasc_exit (void)
{
uart_unregister_driver(&danubeasc_reg);
}