Commit 912c5dae authored by David Woodhouse's avatar David Woodhouse

Update CPM UART driver according to feedback from Dan Malek.

Patch from Pantelis Antoniou <panto@intracom.gr>
parent 3a71cfd5
......@@ -25,7 +25,9 @@
#define SERIAL_CPM_MINOR 42
#endif
#define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC)
#define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC)
#define IS_DISCARDING(pinfo) (pinfo->flags & FLAG_DISCARDING)
#define FLAG_DISCARDING 0x00000004 /* when set, don't discard */
#define FLAG_SMC 0x00000002
#define FLAG_CONSOLE 0x00000001
......@@ -44,29 +46,30 @@
#define TX_BUF_SIZE 32
struct uart_cpm_port {
struct uart_port port;
u16 rx_nrfifos;
u16 rx_fifosize;
u16 tx_nrfifos;
u16 tx_fifosize;
smc_t *smcp;
volatile smc_uart_t *smcup;
scc_t *sccp;
scc_uart_t *sccup;
volatile cbd_t *rx_bd_base;
volatile cbd_t *rx_cur;
volatile cbd_t *tx_bd_base;
volatile cbd_t *tx_cur;
unsigned char *tx_buf;
unsigned char *rx_buf;
u32 flags;
void (*set_lineif) (struct uart_cpm_port *);
u8 brg;
uint dp_addr;
void *mem_addr;
dma_addr_t dma_addr;
int baud;
int bits;
struct uart_port port;
u16 rx_nrfifos;
u16 rx_fifosize;
u16 tx_nrfifos;
u16 tx_fifosize;
smc_t *smcp;
smc_uart_t *smcup;
scc_t *sccp;
scc_uart_t *sccup;
volatile cbd_t *rx_bd_base;
volatile cbd_t *rx_cur;
volatile cbd_t *tx_bd_base;
volatile cbd_t *tx_cur;
unsigned char *tx_buf;
unsigned char *rx_buf;
u32 flags;
void (*set_lineif)(struct uart_cpm_port *);
u8 brg;
uint dp_addr;
void *mem_addr;
dma_addr_t dma_addr;
/* helpers */
int baud;
int bits;
};
extern int cpm_uart_port_map[UART_NR];
......@@ -74,16 +77,16 @@ extern int cpm_uart_nr;
extern struct uart_cpm_port cpm_uart_ports[UART_NR];
/* these are located in their respective files */
extern void cpm_line_cr_cmd(int line, int cmd);
extern int cpm_uart_init_portdesc(void);
extern int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
extern void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
void cpm_line_cr_cmd(int line, int cmd);
int cpm_uart_init_portdesc(void);
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
extern void smc1_lineif(struct uart_cpm_port *pinfo);
extern void smc2_lineif(struct uart_cpm_port *pinfo);
extern void scc1_lineif(struct uart_cpm_port *pinfo);
extern void scc2_lineif(struct uart_cpm_port *pinfo);
extern void scc3_lineif(struct uart_cpm_port *pinfo);
extern void scc4_lineif(struct uart_cpm_port *pinfo);
void smc1_lineif(struct uart_cpm_port *pinfo);
void smc2_lineif(struct uart_cpm_port *pinfo);
void scc1_lineif(struct uart_cpm_port *pinfo);
void scc2_lineif(struct uart_cpm_port *pinfo);
void scc3_lineif(struct uart_cpm_port *pinfo);
void scc4_lineif(struct uart_cpm_port *pinfo);
#endif /* CPM_UART_H */
#endif /* CPM_UART_H */
......@@ -30,7 +30,6 @@
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
......@@ -51,6 +50,7 @@
#endif
#include <linux/serial_core.h>
#include <linux/kernel.h>
#include "cpm_uart.h"
......@@ -61,6 +61,14 @@ int cpm_uart_port_map[UART_NR];
/* How many ports did we config as uarts */
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);
/**************************************************************/
/*
* Check, if transmit buffers are processed
*/
......@@ -114,78 +122,6 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
sccp->scc_sccm &= ~UART_SCCM_TX;
}
/*
* Transmit characters, refill buffer descriptor, if possible
*/
static int cpm_uart_tx_pump(struct uart_port *port)
{
volatile cbd_t *bdp;
unsigned char *p;
int count;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
struct circ_buf *xmit = &port->info->xmit;
/* Handle xon/xoff */
if (port->x_char) {
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
p = bus_to_virt(bdp->cbd_bufaddr);
*p++ = xmit->buf[xmit->tail];
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
pinfo->tx_cur = bdp;
port->icount.tx++;
port->x_char = 0;
return 1;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
cpm_uart_stop_tx(port, 0);
return 0;
}
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
p = bus_to_virt(bdp->cbd_bufaddr);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
count++;
if (xmit->head == xmit->tail)
break;
}
bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
}
pinfo->tx_cur = bdp;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
cpm_uart_stop_tx(port, 0);
return 0;
}
return 1;
}
/*
* Start transmitter
*/
......@@ -197,6 +133,10 @@ 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;
......@@ -420,7 +360,6 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
static int cpm_uart_startup(struct uart_port *port)
{
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
int retval;
pr_debug("CPM uart[%d]:startup\n", port->line);
......@@ -430,34 +369,9 @@ 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;
}
/*
* Reinit buffer descriptors
*/
static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
{
int i;
volatile cbd_t *bdp;
pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
for (bdp = pinfo->rx_cur = pinfo->rx_bd_base, i = 0; i < pinfo->rx_nrfifos; i++, bdp++)
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP);
for (bdp = pinfo->tx_cur = pinfo->tx_bd_base, i = 0; i < pinfo->tx_nrfifos; i++, bdp++)
bdp->cbd_sc = BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP);
}
/*
* Shutdown the uart
*/
......@@ -484,160 +398,8 @@ static void cpm_uart_shutdown(struct uart_port *port)
}
/* Shut them really down and reinit buffer descriptors */
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_STOP_TX);
cpm_uart_initbd(pinfo);
}
}
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int bits, u16 scval)
{
volatile scc_t *scp;
volatile scc_uart_t *sup;
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;
/* 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->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;
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
}
/* 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;
bdp++;
}
/* Store address */
pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
/* Set up the uart parameters in the
* parameter ram.
*/
cpm_set_scc_fcr(sup);
sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
sup->scc_maxidl = pinfo->rx_fifosize;
sup->scc_brkcr = 1;
sup->scc_parec = 0;
sup->scc_frmec = 0;
sup->scc_nosec = 0;
sup->scc_brkec = 0;
sup->scc_uaddr1 = 0;
sup->scc_uaddr2 = 0;
sup->scc_toseq = 0;
sup->scc_char1 = 0x8000;
sup->scc_char2 = 0x8000;
sup->scc_char3 = 0x8000;
sup->scc_char4 = 0x8000;
sup->scc_char5 = 0x8000;
sup->scc_char6 = 0x8000;
sup->scc_char7 = 0x8000;
sup->scc_char8 = 0x8000;
sup->scc_rccm = 0xc0ff;
/* Send the CPM an initialize command.
*/
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
/* Set UART mode, 8 bit, no parity, one stop.
* Enable receive and transmit.
*/
scp->scc_gsmrh = 0;
scp->scc_gsmrl =
(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_scce = 0xffff;
scp->scc_dsr = 0x7e7e;
scp->scc_psmr = (bits << 12) | scval;
scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval)
{
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;
/* Set up the uart parameters in the
* parameter ram.
*/
cpm_set_smc_fcr(up);
/* Using idle charater time requires some additional tuning. */
up->smc_mrblr = pinfo->rx_fifosize;
up->smc_maxidl = pinfo->rx_fifosize;
up->smc_brkcr = 1;
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
/* Set UART mode, according to the parameters */
sp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
/* Enable only rx interrupts clear all pending events. */
sp->smc_smcm = SMCM_RX;
sp->smc_smce = 0xff;
sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
}
static void cpm_uart_set_termios(struct uart_port *port,
......@@ -648,25 +410,39 @@ static void cpm_uart_set_termios(struct uart_port *port,
u16 cval, scval;
int bits, sbits;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
volatile cbd_t *bdp;
pr_debug("CPM uart[%d]:set_termios\n", port->line);
spin_lock_irqsave(&port->lock, flags);
/* Disable UART interrupts */
/* 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 a previous configuration exists wait 2+1 character times
* for tx to finish
*/
if (pinfo->baud != 0 && pinfo->bits != 0)
/* 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;
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(pinfo->port.line, CPM_CR_STOP_TX);
......@@ -679,9 +455,6 @@ static void cpm_uart_set_termios(struct uart_port *port,
/* Send the CPM an initialize command. */
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
/* init bds */
cpm_uart_initbd(pinfo);
spin_unlock_irqrestore(&port->lock, flags);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
......@@ -782,6 +555,7 @@ static void cpm_uart_set_termios(struct uart_port *port,
pinfo->baud = baud;
pinfo->bits = bits;
pinfo->flags &= ~FLAG_DISCARDING;
spin_unlock_irqrestore(&port->lock, flags);
}
......@@ -812,6 +586,229 @@ static int cpm_uart_verify_port(struct uart_port *port,
return ret;
}
/*
* Transmit characters, refill buffer descriptor, if possible
*/
static int cpm_uart_tx_pump(struct uart_port *port)
{
volatile cbd_t *bdp;
unsigned char *p;
int count;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
struct circ_buf *xmit = &port->info->xmit;
/* Handle xon/xoff */
if (port->x_char) {
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
p = bus_to_virt(bdp->cbd_bufaddr);
*p++ = xmit->buf[xmit->tail];
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
pinfo->tx_cur = bdp;
port->icount.tx++;
port->x_char = 0;
return 1;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
cpm_uart_stop_tx(port, 0);
return 0;
}
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
p = bus_to_virt(bdp->cbd_bufaddr);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
count++;
if (xmit->head == xmit->tail)
break;
}
bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base;
else
bdp++;
}
pinfo->tx_cur = bdp;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
cpm_uart_stop_tx(port, 0);
return 0;
}
return 1;
}
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int bits, u16 scval)
{
volatile scc_t *scp;
volatile scc_uart_t *sup;
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;
/* 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->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;
bdp++;
}
/* Store address */
pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
/* Set up the uart parameters in the
* parameter ram.
*/
cpm_set_scc_fcr(sup);
sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
sup->scc_maxidl = pinfo->rx_fifosize;
sup->scc_brkcr = 1;
sup->scc_parec = 0;
sup->scc_frmec = 0;
sup->scc_nosec = 0;
sup->scc_brkec = 0;
sup->scc_uaddr1 = 0;
sup->scc_uaddr2 = 0;
sup->scc_toseq = 0;
sup->scc_char1 = 0x8000;
sup->scc_char2 = 0x8000;
sup->scc_char3 = 0x8000;
sup->scc_char4 = 0x8000;
sup->scc_char5 = 0x8000;
sup->scc_char6 = 0x8000;
sup->scc_char7 = 0x8000;
sup->scc_char8 = 0x8000;
sup->scc_rccm = 0xc0ff;
/* Send the CPM an initialize command.
*/
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
/* Set UART mode, 8 bit, no parity, one stop.
* Enable receive and transmit.
*/
scp->scc_gsmrh = 0;
scp->scc_gsmrl =
(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_scce = 0xffff;
scp->scc_dsr = 0x7e7e;
scp->scc_psmr = (bits << 12) | scval;
scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval)
{
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;
/* Set up the uart parameters in the
* parameter ram.
*/
cpm_set_smc_fcr(up);
/* Using idle charater time requires some additional tuning. */
up->smc_mrblr = pinfo->rx_fifosize;
up->smc_maxidl = pinfo->rx_fifosize;
up->smc_brkcr = 1;
cpm_line_cr_cmd(pinfo->port.line, CPM_CR_INIT_TRX);
/* Set UART mode, according to the parameters */
sp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
/* Enable only rx interrupts clear all pending events. */
sp->smc_smcm = SMCM_RX;
sp->smc_smce = 0xff;
sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
}
/*
* Initialize port. This is called from early_console stuff
* so we have to be careful here !
......@@ -976,6 +973,9 @@ 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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment