Commit 311c4627 authored by Kumar Gala's avatar Kumar Gala Committed by Linus Torvalds

[PATCH] cpm_uart: Fix dpram allocation and non-console uarts

* Makes dpram allocations work
* Makes non-console UART work on both 8xx and 82xx
* Fixed whitespace in files that were touched
Signed-off-by: default avatarVitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: default avatarPantelis Antoniou <panto@intracom.gr>
Signed-off-by: default avatarKumar Gala <kumar.gala@freescale.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3077a260
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#define TX_NUM_FIFO 4 #define TX_NUM_FIFO 4
#define TX_BUF_SIZE 32 #define TX_BUF_SIZE 32
#define SCC_WAIT_CLOSING 100
struct uart_cpm_port { struct uart_cpm_port {
struct uart_port port; struct uart_port port;
u16 rx_nrfifos; u16 rx_nrfifos;
...@@ -67,6 +69,8 @@ struct uart_cpm_port { ...@@ -67,6 +69,8 @@ struct uart_cpm_port {
int bits; int bits;
/* Keep track of 'odd' SMC2 wirings */ /* Keep track of 'odd' SMC2 wirings */
int is_portb; int is_portb;
/* wait on close if needed */
int wait_closing;
}; };
extern int cpm_uart_port_map[UART_NR]; extern int cpm_uart_port_map[UART_NR];
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* *
* Copyright (C) 2004 Freescale Semiconductor, Inc. * Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A. * (C) 2004 Intracom, S.A.
* (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -70,6 +71,20 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo); ...@@ -70,6 +71,20 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/ /**************************************************************/
static inline unsigned long cpu2cpm_addr(void *addr)
{
if ((unsigned long)addr >= CPM_ADDR)
return (unsigned long)addr;
return virt_to_bus(addr);
}
static inline void *cpm2cpu_addr(unsigned long addr)
{
if (addr >= CPM_ADDR)
return (void *)addr;
return bus_to_virt(addr);
}
/* /*
* Check, if transmit buffers are processed * Check, if transmit buffers are processed
*/ */
...@@ -143,10 +158,13 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) ...@@ -143,10 +158,13 @@ static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
} }
if (cpm_uart_tx_pump(port) != 0) { if (cpm_uart_tx_pump(port) != 0) {
if (IS_SMC(pinfo)) if (IS_SMC(pinfo)) {
smcp->smc_smcm |= SMCM_TX; smcp->smc_smcm |= SMCM_TX;
else smcp->smc_smcmr |= SMCMR_TEN;
} else {
sccp->scc_sccm |= UART_SCCM_TX; sccp->scc_sccm |= UART_SCCM_TX;
pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT;
}
} }
} }
...@@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) ...@@ -243,7 +261,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
} }
/* get pointer */ /* get pointer */
cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr); cp = cpm2cpu_addr(bdp->cbd_bufaddr);
/* loop through the buffer */ /* loop through the buffer */
while (i-- > 0) { while (i-- > 0) {
...@@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs) ...@@ -265,13 +283,14 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
} /* End while (i--) */ } /* End while (i--) */
/* This BD is ready to be used again. Clear status. get next */ /* This BD is ready to be used again. Clear status. get next */
bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
bdp->cbd_sc |= BD_SC_EMPTY; bdp->cbd_sc |= BD_SC_EMPTY;
if (bdp->cbd_sc & BD_SC_WRAP) if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->rx_bd_base; bdp = pinfo->rx_bd_base;
else else
bdp++; bdp++;
} /* End for (;;) */ } /* End for (;;) */
/* Write back buffer pointer */ /* Write back buffer pointer */
...@@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs) ...@@ -336,22 +355,22 @@ static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
if (IS_SMC(pinfo)) { if (IS_SMC(pinfo)) {
events = smcp->smc_smce; events = smcp->smc_smce;
smcp->smc_smce = events;
if (events & SMCM_BRKE) if (events & SMCM_BRKE)
uart_handle_break(port); uart_handle_break(port);
if (events & SMCM_RX) if (events & SMCM_RX)
cpm_uart_int_rx(port, regs); cpm_uart_int_rx(port, regs);
if (events & SMCM_TX) if (events & SMCM_TX)
cpm_uart_int_tx(port, regs); cpm_uart_int_tx(port, regs);
smcp->smc_smce = events;
} else { } else {
events = sccp->scc_scce; events = sccp->scc_scce;
sccp->scc_scce = events;
if (events & UART_SCCM_BRKE) if (events & UART_SCCM_BRKE)
uart_handle_break(port); uart_handle_break(port);
if (events & UART_SCCM_RX) if (events & UART_SCCM_RX)
cpm_uart_int_rx(port, regs); cpm_uart_int_rx(port, regs);
if (events & UART_SCCM_TX) if (events & UART_SCCM_TX)
cpm_uart_int_tx(port, regs); cpm_uart_int_tx(port, regs);
sccp->scc_scce = events;
} }
return (events) ? IRQ_HANDLED : IRQ_NONE; return (events) ? IRQ_HANDLED : IRQ_NONE;
} }
...@@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port) ...@@ -360,6 +379,7 @@ static int cpm_uart_startup(struct uart_port *port)
{ {
int retval; int retval;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
int line = pinfo - cpm_uart_ports;
pr_debug("CPM uart[%d]:startup\n", port->line); pr_debug("CPM uart[%d]:startup\n", port->line);
...@@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port) ...@@ -376,9 +396,19 @@ static int cpm_uart_startup(struct uart_port *port)
pinfo->sccp->scc_sccm |= UART_SCCM_RX; pinfo->sccp->scc_sccm |= UART_SCCM_RX;
} }
if (!(pinfo->flags & FLAG_CONSOLE))
cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
return 0; return 0;
} }
inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
{
unsigned long target_jiffies = jiffies + pinfo->wait_closing;
while (!time_after(jiffies, target_jiffies))
schedule();
}
/* /*
* Shutdown the uart * Shutdown the uart
*/ */
...@@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port) ...@@ -394,6 +424,12 @@ static void cpm_uart_shutdown(struct uart_port *port)
/* If the port is not the console, disable Rx and Tx. */ /* If the port is not the console, disable Rx and Tx. */
if (!(pinfo->flags & FLAG_CONSOLE)) { if (!(pinfo->flags & FLAG_CONSOLE)) {
/* Wait for all the BDs marked sent */
while(!cpm_uart_tx_empty(port))
schedule_timeout(2);
if(pinfo->wait_closing)
cpm_uart_wait_until_send(pinfo);
/* Stop uarts */ /* Stop uarts */
if (IS_SMC(pinfo)) { if (IS_SMC(pinfo)) {
volatile smc_t *smcp = pinfo->smcp; volatile smc_t *smcp = pinfo->smcp;
...@@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port) ...@@ -569,7 +605,8 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */ /* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur; bdp = pinfo->tx_cur;
p = bus_to_virt(bdp->cbd_bufaddr); p = cpm2cpu_addr(bdp->cbd_bufaddr);
*p++ = xmit->buf[xmit->tail]; *p++ = xmit->buf[xmit->tail];
bdp->cbd_datlen = 1; bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY; bdp->cbd_sc |= BD_SC_READY;
...@@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) ...@@ -595,7 +632,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0; count = 0;
p = bus_to_virt(bdp->cbd_bufaddr); p = cpm2cpu_addr(bdp->cbd_bufaddr);
while (count < pinfo->tx_fifosize) { while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail]; *p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
...@@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) ...@@ -606,6 +643,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
} }
bdp->cbd_datlen = count; bdp->cbd_datlen = count;
bdp->cbd_sc |= BD_SC_READY; bdp->cbd_sc |= BD_SC_READY;
__asm__("eieio");
/* Get next BD. */ /* Get next BD. */
if (bdp->cbd_sc & BD_SC_WRAP) if (bdp->cbd_sc & BD_SC_WRAP)
bdp = pinfo->tx_bd_base; bdp = pinfo->tx_bd_base;
...@@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) ...@@ -643,12 +681,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr; mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base; bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) { for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT; bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
mem_addr += pinfo->rx_fifosize; mem_addr += pinfo->rx_fifosize;
} }
bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
/* Set the physical address of the host memory /* Set the physical address of the host memory
...@@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo) ...@@ -658,12 +696,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize); mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base; bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) { for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_INTRPT; bdp->cbd_sc = BD_SC_INTRPT;
mem_addr += pinfo->tx_fifosize; mem_addr += pinfo->tx_fifosize;
} }
bdp->cbd_bufaddr = virt_to_bus(mem_addr); bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT; bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
} }
...@@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo) ...@@ -763,6 +801,8 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
/* Using idle charater time requires some additional tuning. */ /* Using idle charater time requires some additional tuning. */
up->smc_mrblr = pinfo->rx_fifosize; up->smc_mrblr = pinfo->rx_fifosize;
up->smc_maxidl = pinfo->rx_fifosize; up->smc_maxidl = pinfo->rx_fifosize;
up->smc_brklen = 0;
up->smc_brkec = 0;
up->smc_brkcr = 1; up->smc_brkcr = 1;
cpm_line_cr_cmd(line, CPM_CR_INIT_TRX); cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
...@@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port) ...@@ -815,6 +855,10 @@ static int cpm_uart_request_port(struct uart_port *port)
return ret; return ret;
cpm_uart_initbd(pinfo); cpm_uart_initbd(pinfo);
if (IS_SMC(pinfo))
cpm_uart_init_smc(pinfo);
else
cpm_uart_init_scc(pinfo);
return 0; return 0;
} }
...@@ -902,6 +946,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { ...@@ -902,6 +946,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.rx_nrfifos = RX_NUM_FIFO, .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE, .rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc1_lineif, .set_lineif = scc1_lineif,
.wait_closing = SCC_WAIT_CLOSING,
}, },
[UART_SCC2] = { [UART_SCC2] = {
.port = { .port = {
...@@ -915,6 +960,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { ...@@ -915,6 +960,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.rx_nrfifos = RX_NUM_FIFO, .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE, .rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc2_lineif, .set_lineif = scc2_lineif,
.wait_closing = SCC_WAIT_CLOSING,
}, },
[UART_SCC3] = { [UART_SCC3] = {
.port = { .port = {
...@@ -928,6 +974,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { ...@@ -928,6 +974,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.rx_nrfifos = RX_NUM_FIFO, .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE, .rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc3_lineif, .set_lineif = scc3_lineif,
.wait_closing = SCC_WAIT_CLOSING,
}, },
[UART_SCC4] = { [UART_SCC4] = {
.port = { .port = {
...@@ -941,6 +988,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = { ...@@ -941,6 +988,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.rx_nrfifos = RX_NUM_FIFO, .rx_nrfifos = RX_NUM_FIFO,
.rx_fifosize = RX_BUF_SIZE, .rx_fifosize = RX_BUF_SIZE,
.set_lineif = scc4_lineif, .set_lineif = scc4_lineif,
.wait_closing = SCC_WAIT_CLOSING,
}, },
}; };
...@@ -983,10 +1031,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, ...@@ -983,10 +1031,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* If the buffer address is in the CPM DPRAM, don't * If the buffer address is in the CPM DPRAM, don't
* convert it. * convert it.
*/ */
if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) cp = cpm2cpu_addr(bdp->cbd_bufaddr);
cp = (unsigned char *) (bdp->cbd_bufaddr);
else
cp = bus_to_virt(bdp->cbd_bufaddr);
*cp = *s; *cp = *s;
...@@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s, ...@@ -1003,10 +1048,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
while ((bdp->cbd_sc & BD_SC_READY) != 0) while ((bdp->cbd_sc & BD_SC_READY) != 0)
; ;
if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR) cp = cpm2cpu_addr(bdp->cbd_bufaddr);
cp = (unsigned char *) (bdp->cbd_bufaddr);
else
cp = bus_to_virt(bdp->cbd_bufaddr);
*cp = 13; *cp = 13;
bdp->cbd_datlen = 1; bdp->cbd_datlen = 1;
......
...@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd) ...@@ -82,6 +82,17 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo) void smc1_lineif(struct uart_cpm_port *pinfo)
{ {
volatile cpm8xx_t *cp = cpmp; volatile cpm8xx_t *cp = cpmp;
(void)cp; /* fix warning */
#if defined (CONFIG_MPC885ADS)
/* Enable SMC1 transceivers */
{
cp->cp_pepar |= 0x000000c0;
cp->cp_pedir &= ~0x000000c0;
cp->cp_peso &= ~0x00000040;
cp->cp_peso |= 0x00000080;
}
#elif defined (CONFIG_MPC86XADS)
unsigned int iobits = 0x000000c0; unsigned int iobits = 0x000000c0;
if (!pinfo->is_portb) { if (!pinfo->is_portb) {
...@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo) ...@@ -93,41 +104,33 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits; ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits; ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
} }
#ifdef CONFIG_MPC885ADS
/* Enable SMC1 transceivers */
{
volatile uint __iomem *bcsr1 = ioremap(BCSR1, 4);
uint tmp;
tmp = in_be32(bcsr1);
tmp &= ~BCSR1_RS232EN_1;
out_be32(bcsr1, tmp);
iounmap(bcsr1);
}
#endif #endif
pinfo->brg = 1; pinfo->brg = 1;
} }
void smc2_lineif(struct uart_cpm_port *pinfo) void smc2_lineif(struct uart_cpm_port *pinfo)
{ {
#ifdef CONFIG_MPC885ADS
volatile cpm8xx_t *cp = cpmp; volatile cpm8xx_t *cp = cpmp;
volatile uint __iomem *bcsr1;
uint tmp;
(void)cp; /* fix warning */
#if defined (CONFIG_MPC885ADS)
cp->cp_pepar |= 0x00000c00; cp->cp_pepar |= 0x00000c00;
cp->cp_pedir &= ~0x00000c00; cp->cp_pedir &= ~0x00000c00;
cp->cp_peso &= ~0x00000400; cp->cp_peso &= ~0x00000400;
cp->cp_peso |= 0x00000800; cp->cp_peso |= 0x00000800;
#elif defined (CONFIG_MPC86XADS)
unsigned int iobits = 0x00000c00;
if (!pinfo->is_portb) {
cp->cp_pbpar |= iobits;
cp->cp_pbdir &= ~iobits;
cp->cp_pbodr &= ~iobits;
} else {
((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
}
/* Enable SMC2 transceivers */
bcsr1 = ioremap(BCSR1, 4);
tmp = in_be32(bcsr1);
tmp &= ~BCSR1_RS232EN_2;
out_be32(bcsr1, tmp);
iounmap(bcsr1);
#endif #endif
pinfo->brg = 2; pinfo->brg = 2;
...@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) ...@@ -185,6 +188,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) + memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize); L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
if (is_con) { if (is_con) {
/* was hostalloc but changed cause it blows away the */
/* large tlb mapping when pinning the kernel area */
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8)); mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
dma_addr = 0; dma_addr = 0;
} else } else
......
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