Index: 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 #include #include -#include -#include +#include +#include #include #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); }