X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fserial%2Fcpm_uart%2Fcpm_uart_core.c;h=34f4c6737d67da310a6970ec1926de372b402068;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=0612e9453eccb7182c91708659cead459a9935df;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 0612e9453..34f4c6737 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -64,8 +64,9 @@ int cpm_uart_nr; /**************************************************************/ static int cpm_uart_tx_pump(struct uart_port *port); -static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval); -static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int sbits, u16 sval); +static void cpm_uart_init_smc(struct uart_cpm_port *pinfo); +static void cpm_uart_init_scc(struct uart_cpm_port *pinfo); +static void cpm_uart_initbd(struct uart_cpm_port *pinfo); /**************************************************************/ @@ -133,10 +134,6 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) pr_debug("CPM uart[%d]:start tx\n", port->line); - /* if in the middle of discarding return */ - if (IS_DISCARDING(pinfo)) - return; - if (IS_SMC(pinfo)) { if (smcp->smc_smcm & SMCM_TX) return; @@ -362,6 +359,7 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) static int cpm_uart_startup(struct uart_port *port) { int retval; + struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; pr_debug("CPM uart[%d]:startup\n", port->line); @@ -370,6 +368,14 @@ static int cpm_uart_startup(struct uart_port *port) if (retval) return retval; + /* Startup rx-int */ + if (IS_SMC(pinfo)) { + pinfo->smcp->smc_smcm |= SMCM_RX; + pinfo->smcp->smc_smcmr |= SMCMR_REN; + } else { + pinfo->sccp->scc_sccm |= UART_SCCM_RX; + } + return 0; } @@ -400,7 +406,8 @@ static void cpm_uart_shutdown(struct uart_port *port) } /* Shut them really down and reinit buffer descriptors */ - cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); + cpm_line_cr_cmd(line, CPM_CR_STOP_TX); + cpm_uart_initbd(pinfo); } } @@ -409,57 +416,14 @@ static void cpm_uart_set_termios(struct uart_port *port, { int baud; unsigned long flags; - u16 cval, scval; + u16 cval, scval, prev_mode; int bits, sbits; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; - int line = pinfo - cpm_uart_ports; - volatile cbd_t *bdp; + volatile smc_t *smcp = pinfo->smcp; + volatile scc_t *sccp = pinfo->sccp; pr_debug("CPM uart[%d]:set_termios\n", port->line); - spin_lock_irqsave(&port->lock, flags); - /* disable uart interrupts */ - if (IS_SMC(pinfo)) - pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); - else - pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); - pinfo->flags |= FLAG_DISCARDING; - spin_unlock_irqrestore(&port->lock, flags); - - /* if previous configuration exists wait for tx to finish */ - if (pinfo->baud != 0 && pinfo->bits != 0) { - - /* point to the last txed bd */ - bdp = pinfo->tx_cur; - if (bdp == pinfo->tx_bd_base) - bdp = pinfo->tx_bd_base + (pinfo->tx_nrfifos - 1); - else - bdp--; - - /* wait for it to be transmitted */ - while ((bdp->cbd_sc & BD_SC_READY) != 0) - schedule(); - - /* and delay for the hw fifo to drain */ - udelay((3 * 1000000 * pinfo->bits) / pinfo->baud); - } - - spin_lock_irqsave(&port->lock, flags); - - /* Send the CPM an initialize command. */ - cpm_line_cr_cmd(line, CPM_CR_STOP_TX); - - /* Stop uart */ - if (IS_SMC(pinfo)) - pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); - else - pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); - - /* Send the CPM an initialize command. */ - cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); - - spin_unlock_irqrestore(&port->lock, flags); - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); /* Character length programmed into the mode register is the @@ -541,24 +505,24 @@ static void cpm_uart_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); - cpm_set_brg(pinfo->brg - 1, baud); - /* Start bit has not been added (so don't, because we would just * subtract it later), and we need to add one for the number of * stops bits (there is always at least one). */ bits++; + if (IS_SMC(pinfo)) { + /* Set the mode register. We want to keep a copy of the + * enables, because we want to put them back if they were + * present. + */ + prev_mode = smcp->smc_smcmr; + smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; + smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); + } else { + sccp->scc_psmr = (sbits << 12) | scval; + } - /* re-init */ - if (IS_SMC(pinfo)) - cpm_uart_init_smc(pinfo, bits, cval); - else - cpm_uart_init_scc(pinfo, sbits, scval); - - pinfo->baud = baud; - pinfo->bits = bits; - - pinfo->flags &= ~FLAG_DISCARDING; + cpm_set_brg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); } @@ -661,44 +625,58 @@ static int cpm_uart_tx_pump(struct uart_port *port) return 1; } -static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int bits, u16 scval) +/* + * init buffer descriptors + */ +static void cpm_uart_initbd(struct uart_cpm_port *pinfo) { - int line = pinfo - cpm_uart_ports; - volatile scc_t *scp; - volatile scc_uart_t *sup; + int i; u8 *mem_addr; volatile cbd_t *bdp; - int i; - pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line); - - scp = pinfo->sccp; - sup = pinfo->sccup; + pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line); /* Set the physical address of the host memory * buffers in the buffer descriptors, and the * virtual address for us to work with. */ - pinfo->rx_cur = pinfo->rx_bd_base; mem_addr = pinfo->mem_addr; - for (bdp = pinfo->rx_bd_base, i = 0; i < pinfo->rx_nrfifos; i++, bdp++) { + bdp = pinfo->rx_cur = pinfo->rx_bd_base; + for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { bdp->cbd_bufaddr = virt_to_bus(mem_addr); - bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP); + bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; mem_addr += pinfo->rx_fifosize; } + + bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; /* Set the physical address of the host memory * buffers in the buffer descriptors, and the * virtual address for us to work with. */ mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); - pinfo->tx_cur = pinfo->tx_bd_base; - for (bdp = pinfo->tx_bd_base, i = 0; i < pinfo->tx_nrfifos; i++, bdp++) { + bdp = pinfo->tx_cur = pinfo->tx_bd_base; + for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { bdp->cbd_bufaddr = virt_to_bus(mem_addr); - bdp->cbd_sc = BD_SC_INTRPT | (i < (pinfo->tx_nrfifos - 1) ? 0 : BD_SC_WRAP); + bdp->cbd_sc = BD_SC_INTRPT; mem_addr += pinfo->tx_fifosize; - bdp++; } + + bdp->cbd_bufaddr = virt_to_bus(mem_addr); + bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; +} + +static void cpm_uart_init_scc(struct uart_cpm_port *pinfo) +{ + int line = pinfo - cpm_uart_ports; + volatile scc_t *scp; + volatile scc_uart_t *sup; + + pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line); + + scp = pinfo->sccp; + sup = pinfo->sccup; /* Store address */ pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE; @@ -742,52 +720,25 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int bits, u16 scval) (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); /* Enable rx interrupts and clear all pending events. */ - scp->scc_sccm = UART_SCCM_RX; + scp->scc_sccm = 0; scp->scc_scce = 0xffff; scp->scc_dsr = 0x7e7e; - scp->scc_psmr = (bits << 12) | scval; + scp->scc_psmr = 0x3000; scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); } -static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval) +static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) { int line = pinfo - cpm_uart_ports; volatile smc_t *sp; volatile smc_uart_t *up; - volatile u8 *mem_addr; - volatile cbd_t *bdp; - int i; pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line); sp = pinfo->smcp; up = pinfo->smcup; - /* Set the physical address of the host memory - * buffers in the buffer descriptors, and the - * virtual address for us to work with. - */ - mem_addr = pinfo->mem_addr; - pinfo->rx_cur = pinfo->rx_bd_base; - for (bdp = pinfo->rx_bd_base, i = 0; i < pinfo->rx_nrfifos; i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); - bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP); - mem_addr += pinfo->rx_fifosize; - } - - /* Set the physical address of the host memory - * buffers in the buffer descriptors, and the - * virtual address for us to work with. - */ - mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); - pinfo->tx_cur = pinfo->tx_bd_base; - for (bdp = pinfo->tx_bd_base, i = 0; i < pinfo->tx_nrfifos; i++, bdp++) { - bdp->cbd_bufaddr = virt_to_bus(mem_addr); - bdp->cbd_sc = BD_SC_INTRPT | (i < (pinfo->tx_nrfifos - 1) ? 0 : BD_SC_WRAP); - mem_addr += pinfo->tx_fifosize; - } - /* Store address */ pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE; pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE; @@ -804,11 +755,13 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval) cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); - /* Set UART mode, according to the parameters */ - sp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; /* Enable only rx interrupts clear all pending events. */ - sp->smc_smcm = SMCM_RX; + sp->smc_smcm = 0; sp->smc_smce = 0xff; sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); @@ -836,10 +789,21 @@ static int cpm_uart_request_port(struct uart_port *port) if (pinfo->set_lineif) pinfo->set_lineif(pinfo); + if (IS_SMC(pinfo)) { + pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); + pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + } else { + pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + } + ret = cpm_uart_allocbuf(pinfo, 0); + if (ret) return ret; + cpm_uart_initbd(pinfo); + return 0; } @@ -975,9 +939,6 @@ static void cpm_uart_console_write(struct console *co, const char *s, volatile cbd_t *bdp, *bdbase; volatile unsigned char *cp; - if (IS_DISCARDING(pinfo)) - return; - /* Get the address of the host memory buffer. */ bdp = pinfo->tx_cur; @@ -1085,10 +1046,26 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) if (pinfo->set_lineif) pinfo->set_lineif(pinfo); + if (IS_SMC(pinfo)) { + pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); + pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + } else { + pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + } + ret = cpm_uart_allocbuf(pinfo, 1); + if (ret) return ret; + cpm_uart_initbd(pinfo); + + if (IS_SMC(pinfo)) + cpm_uart_init_smc(pinfo); + else + cpm_uart_init_scc(pinfo); + uart_set_options(port, co, baud, parity, bits, flow); return 0;