Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
912c5dae
Commit
912c5dae
authored
Jun 21, 2004
by
David Woodhouse
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update CPM UART driver according to feedback from Dan Malek.
Patch from Pantelis Antoniou <panto@intracom.gr>
parent
3a71cfd5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
299 additions
and
296 deletions
+299
-296
drivers/serial/cpm_uart/cpm_uart.h
drivers/serial/cpm_uart/cpm_uart.h
+38
-35
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/cpm_uart/cpm_uart_core.c
+261
-261
No files found.
drivers/serial/cpm_uart/cpm_uart.h
View file @
912c5dae
...
...
@@ -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 */
drivers/serial/cpm_uart/cpm_uart_core.c
View file @
912c5dae
...
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment