Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci-2.6.23
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci-2.6.23
Commits
36764631
Commit
36764631
authored
Jun 29, 2006
by
David S. Miller
Committed by
David S. Miller
Jun 29, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SERIAL] sunzilog: Convert to of_driver.
Signed-off-by:
David S. Miller
<
davem@davemloft.net
>
parent
8f96cd1a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
258 additions
and
527 deletions
+258
-527
drivers/serial/sunzilog.c
drivers/serial/sunzilog.c
+258
-527
No files found.
drivers/serial/sunzilog.c
View file @
36764631
/*
* sunzilog.c
/* sunzilog.c: Zilog serial driver for Sparc systems.
*
* Driver for Zilog serial chips found on Sun workstations and
* servers. This driver could actually be made more generic.
...
...
@@ -10,7 +9,7 @@
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
* Copyright (C) 2002
David S. Miller (davem@redhat.com
)
* Copyright (C) 2002
, 2006 David S. Miller (davem@davemloft.net
)
*/
#include <linux/config.h>
...
...
@@ -38,10 +37,8 @@
#include <asm/io.h>
#include <asm/irq.h>
#ifdef CONFIG_SPARC64
#include <asm/fhc.h>
#endif
#include <asm/sbus.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
...
...
@@ -65,7 +62,7 @@
#define ZSDELAY()
#define ZSDELAY_LONG()
#define ZS_WSYNC(__channel) \
sbus_
readb(&((__channel)->control))
readb(&((__channel)->control))
#endif
static
int
num_sunzilog
;
...
...
@@ -107,7 +104,7 @@ struct uart_sunzilog_port {
unsigned
char
prev_status
;
#ifdef CONFIG_SERIO
struct
serio
*
serio
;
struct
serio
serio
;
int
serio_open
;
#endif
};
...
...
@@ -138,9 +135,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
{
unsigned
char
retval
;
sbus_
writeb
(
reg
,
&
channel
->
control
);
writeb
(
reg
,
&
channel
->
control
);
ZSDELAY
();
retval
=
sbus_
readb
(
&
channel
->
control
);
retval
=
readb
(
&
channel
->
control
);
ZSDELAY
();
return
retval
;
...
...
@@ -149,9 +146,9 @@ static unsigned char read_zsreg(struct zilog_channel __iomem *channel,
static
void
write_zsreg
(
struct
zilog_channel
__iomem
*
channel
,
unsigned
char
reg
,
unsigned
char
value
)
{
sbus_
writeb
(
reg
,
&
channel
->
control
);
writeb
(
reg
,
&
channel
->
control
);
ZSDELAY
();
sbus_
writeb
(
value
,
&
channel
->
control
);
writeb
(
value
,
&
channel
->
control
);
ZSDELAY
();
}
...
...
@@ -162,17 +159,17 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel)
for
(
i
=
0
;
i
<
32
;
i
++
)
{
unsigned
char
regval
;
regval
=
sbus_
readb
(
&
channel
->
control
);
regval
=
readb
(
&
channel
->
control
);
ZSDELAY
();
if
(
regval
&
Rx_CH_AV
)
break
;
regval
=
read_zsreg
(
channel
,
R1
);
sbus_
readb
(
&
channel
->
data
);
readb
(
&
channel
->
data
);
ZSDELAY
();
if
(
regval
&
(
PAR_ERR
|
Rx_OVR
|
CRC_ERR
))
{
sbus_
writeb
(
ERR_RES
,
&
channel
->
control
);
writeb
(
ERR_RES
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
}
...
...
@@ -194,7 +191,7 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *
udelay
(
100
);
}
sbus_
writeb
(
ERR_RES
,
&
channel
->
control
);
writeb
(
ERR_RES
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -291,7 +288,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
/* Stop-A is handled by drivers/char/keyboard.c now. */
#ifdef CONFIG_SERIO
if
(
up
->
serio_open
)
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
#endif
}
else
if
(
ZS_IS_MOUSE
(
up
))
{
int
ret
=
suncore_mouse_baud_detection
(
ch
,
is_break
);
...
...
@@ -306,7 +303,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
case
0
:
#ifdef CONFIG_SERIO
if
(
up
->
serio_open
)
serio_interrupt
(
up
->
serio
,
ch
,
0
,
regs
);
serio_interrupt
(
&
up
->
serio
,
ch
,
0
,
regs
);
#endif
break
;
};
...
...
@@ -330,12 +327,12 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
r1
=
read_zsreg
(
channel
,
R1
);
if
(
r1
&
(
PAR_ERR
|
Rx_OVR
|
CRC_ERR
))
{
sbus_
writeb
(
ERR_RES
,
&
channel
->
control
);
writeb
(
ERR_RES
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
}
ch
=
sbus_
readb
(
&
channel
->
control
);
ch
=
readb
(
&
channel
->
control
);
ZSDELAY
();
/* This funny hack depends upon BRK_ABRT not interfering
...
...
@@ -347,7 +344,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
if
(
!
(
ch
&
Rx_CH_AV
))
break
;
ch
=
sbus_
readb
(
&
channel
->
data
);
ch
=
readb
(
&
channel
->
data
);
ZSDELAY
();
ch
&=
up
->
parity_mask
;
...
...
@@ -406,10 +403,10 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
{
unsigned
char
status
;
status
=
sbus_
readb
(
&
channel
->
control
);
status
=
readb
(
&
channel
->
control
);
ZSDELAY
();
sbus_
writeb
(
RES_EXT_INT
,
&
channel
->
control
);
writeb
(
RES_EXT_INT
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -421,7 +418,7 @@ static void sunzilog_status_handle(struct uart_sunzilog_port *up,
* confusing the PROM.
*/
while
(
1
)
{
status
=
sbus_
readb
(
&
channel
->
control
);
status
=
readb
(
&
channel
->
control
);
ZSDELAY
();
if
(
!
(
status
&
BRK_ABRT
))
break
;
...
...
@@ -458,7 +455,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
struct
circ_buf
*
xmit
;
if
(
ZS_IS_CONS
(
up
))
{
unsigned
char
status
=
sbus_
readb
(
&
channel
->
control
);
unsigned
char
status
=
readb
(
&
channel
->
control
);
ZSDELAY
();
/* TX still busy? Just wait for the next TX done interrupt.
...
...
@@ -487,7 +484,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
if
(
up
->
port
.
x_char
)
{
up
->
flags
|=
SUNZILOG_FLAG_TX_ACTIVE
;
sbus_
writeb
(
up
->
port
.
x_char
,
&
channel
->
data
);
writeb
(
up
->
port
.
x_char
,
&
channel
->
data
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -506,7 +503,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
goto
ack_tx_int
;
up
->
flags
|=
SUNZILOG_FLAG_TX_ACTIVE
;
sbus_
writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -519,7 +516,7 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up,
return
;
ack_tx_int:
sbus_
writeb
(
RES_Tx_P
,
&
channel
->
control
);
writeb
(
RES_Tx_P
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
}
...
...
@@ -540,7 +537,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Channel A */
tty
=
NULL
;
if
(
r3
&
(
CHAEXT
|
CHATxIP
|
CHARxIP
))
{
sbus_
writeb
(
RES_H_IUS
,
&
channel
->
control
);
writeb
(
RES_H_IUS
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -563,7 +560,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id, struct pt_regs *reg
spin_lock
(
&
up
->
port
.
lock
);
tty
=
NULL
;
if
(
r3
&
(
CHBEXT
|
CHBTxIP
|
CHBRxIP
))
{
sbus_
writeb
(
RES_H_IUS
,
&
channel
->
control
);
writeb
(
RES_H_IUS
,
&
channel
->
control
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -594,7 +591,7 @@ static __inline__ unsigned char sunzilog_read_channel_status(struct uart_port *p
unsigned
char
status
;
channel
=
ZILOG_CHANNEL_FROM_PORT
(
port
);
status
=
sbus_
readb
(
&
channel
->
control
);
status
=
readb
(
&
channel
->
control
);
ZSDELAY
();
return
status
;
...
...
@@ -682,7 +679,7 @@ static void sunzilog_start_tx(struct uart_port *port)
up
->
flags
|=
SUNZILOG_FLAG_TX_ACTIVE
;
up
->
flags
&=
~
SUNZILOG_FLAG_TX_STOPPED
;
status
=
sbus_
readb
(
&
channel
->
control
);
status
=
readb
(
&
channel
->
control
);
ZSDELAY
();
/* TX busy? Just wait for the TX done interrupt. */
...
...
@@ -693,7 +690,7 @@ static void sunzilog_start_tx(struct uart_port *port)
* IRQ sending engine.
*/
if
(
port
->
x_char
)
{
sbus_
writeb
(
port
->
x_char
,
&
channel
->
data
);
writeb
(
port
->
x_char
,
&
channel
->
data
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -702,7 +699,7 @@ static void sunzilog_start_tx(struct uart_port *port)
}
else
{
struct
circ_buf
*
xmit
=
&
port
->
info
->
xmit
;
sbus_
writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
writeb
(
xmit
->
buf
[
xmit
->
tail
],
&
channel
->
data
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
...
...
@@ -779,7 +776,7 @@ static void __sunzilog_startup(struct uart_sunzilog_port *up)
struct
zilog_channel
__iomem
*
channel
;
channel
=
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
);
up
->
prev_status
=
sbus_
readb
(
&
channel
->
control
);
up
->
prev_status
=
readb
(
&
channel
->
control
);
/* Enable receiver and transmitter. */
up
->
curregs
[
R3
]
|=
RxENAB
;
...
...
@@ -963,7 +960,7 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios,
static
const
char
*
sunzilog_type
(
struct
uart_port
*
port
)
{
return
"
SunZilog
"
;
return
"
zs
"
;
}
/* We do not request/release mappings of the registers here, this
...
...
@@ -1012,7 +1009,6 @@ static struct uart_sunzilog_port *sunzilog_port_table;
static
struct
zilog_layout
__iomem
**
sunzilog_chip_regs
;
static
struct
uart_sunzilog_port
*
sunzilog_irq_chain
;
static
int
zilog_irq
=
-
1
;
static
struct
uart_driver
sunzilog_reg
=
{
.
owner
=
THIS_MODULE
,
...
...
@@ -1021,232 +1017,47 @@ static struct uart_driver sunzilog_reg = {
.
major
=
TTY_MAJOR
,
};
static
void
*
__init
alloc_one_table
(
unsigned
long
size
)
static
int
__init
sunzilog_alloc_tables
(
void
)
{
void
*
ret
;
ret
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
ret
!=
NULL
)
memset
(
ret
,
0
,
size
);
struct
uart_sunzilog_port
*
up
;
unsigned
long
size
;
int
i
;
return
ret
;
}
size
=
NUM_CHANNELS
*
sizeof
(
struct
uart_sunzilog_port
);
sunzilog_port_table
=
kzalloc
(
size
,
GFP_KERNEL
);
if
(
!
sunzilog_port_table
)
return
-
ENOMEM
;
static
void
__init
sunzilog_alloc_tables
(
void
)
{
sunzilog_port_table
=
alloc_one_table
(
NUM_CHANNELS
*
sizeof
(
struct
uart_sunzilog_port
));
sunzilog_chip_regs
=
alloc_one_table
(
NUM_SUNZILOG
*
sizeof
(
struct
zilog_layout
__iomem
*
));
if
(
sunzilog_port_table
==
NULL
||
sunzilog_chip_regs
==
NULL
)
{
prom_printf
(
"SunZilog: Cannot allocate tables.
\n
"
);
prom_halt
();
}
}
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
up
=
&
sunzilog_port_table
[
i
];
#ifdef CONFIG_SPARC64
spin_lock_init
(
&
up
->
port
.
lock
);
/* We used to attempt to use the address property of the Zilog device node
* but that totally is not necessary on sparc64.
*/
static
struct
zilog_layout
__iomem
*
__init
get_zs_sun4u
(
int
chip
,
int
zsnode
)
{
void
__iomem
*
mapped_addr
;
unsigned
int
sun4u_ino
;
struct
sbus_bus
*
sbus
=
NULL
;
struct
sbus_dev
*
sdev
=
NULL
;
int
err
;
if
(
i
==
0
)
sunzilog_irq_chain
=
up
;
if
(
central_bus
==
NULL
)
{
for_each_sbus
(
sbus
)
{
for_each_sbusdev
(
sdev
,
sbus
)
{
if
(
sdev
->
prom_node
==
zsnode
)
goto
found
;
}
}
}
found:
if
(
sdev
==
NULL
&&
central_bus
==
NULL
)
{
prom_printf
(
"SunZilog: sdev&¢ral == NULL for "
"Zilog %d in get_zs_sun4u.
\n
"
,
chip
);
prom_halt
();
}
if
(
central_bus
==
NULL
)
{
mapped_addr
=
sbus_ioremap
(
&
sdev
->
resource
[
0
],
0
,
PAGE_SIZE
,
"Zilog Registers"
);
}
else
{
struct
linux_prom_registers
zsregs
[
1
];
err
=
prom_getproperty
(
zsnode
,
"reg"
,
(
char
*
)
&
zsregs
[
0
],
sizeof
(
zsregs
));
if
(
err
==
-
1
)
{
prom_printf
(
"SunZilog: Cannot map "
"Zilog %d regs on "
"central bus.
\n
"
,
chip
);
prom_halt
();
}
apply_fhc_ranges
(
central_bus
->
child
,
&
zsregs
[
0
],
1
);
apply_central_ranges
(
central_bus
,
&
zsregs
[
0
],
1
);
mapped_addr
=
(
void
__iomem
*
)
((((
u64
)
zsregs
[
0
].
which_io
)
<<
32UL
)
|
((
u64
)
zsregs
[
0
].
phys_addr
));
if
(
i
<
NUM_CHANNELS
-
1
)
up
->
next
=
up
+
1
;
else
up
->
next
=
NULL
;
}
if
(
zilog_irq
==
-
1
)
{
if
(
central_bus
)
{
unsigned
long
iclr
,
imap
;
iclr
=
central_bus
->
child
->
fhc_regs
.
uregs
+
FHC_UREGS_ICLR
;
imap
=
central_bus
->
child
->
fhc_regs
.
uregs
+
FHC_UREGS_IMAP
;
zilog_irq
=
build_irq
(
0
,
iclr
,
imap
);
}
else
{
err
=
prom_getproperty
(
zsnode
,
"interrupts"
,
(
char
*
)
&
sun4u_ino
,
sizeof
(
sun4u_ino
));
zilog_irq
=
sbus_build_irq
(
sbus_root
,
sun4u_ino
);
}
size
=
NUM_SUNZILOG
*
sizeof
(
struct
zilog_layout
__iomem
*
);
sunzilog_chip_regs
=
kzalloc
(
size
,
GFP_KERNEL
);
if
(
!
sunzilog_chip_regs
)
{
kfree
(
sunzilog_port_table
);
sunzilog_irq_chain
=
NULL
;
return
-
ENOMEM
;
}
return
(
struct
zilog_layout
__iomem
*
)
mapped_addr
;
return
0
;
}
#else
/* CONFIG_SPARC64 */
/*
* XXX The sun4d case is utterly screwed: it tries to re-walk the tree
* (for the 3rd time) in order to find bootbus and cpu. Streamline it.
*/
static
struct
zilog_layout
__iomem
*
__init
get_zs_sun4cmd
(
int
chip
,
int
node
)
static
void
sunzilog_free_tables
(
void
)
{
struct
linux_prom_irqs
irq_info
[
2
];
void
__iomem
*
mapped_addr
=
NULL
;
int
zsnode
,
cpunode
,
bbnode
;
struct
linux_prom_registers
zsreg
[
4
];
struct
resource
res
;
if
(
sparc_cpu_model
==
sun4d
)
{
int
walk
;
zsnode
=
0
;
bbnode
=
0
;
cpunode
=
0
;
for
(
walk
=
prom_getchild
(
prom_root_node
);
(
walk
=
prom_searchsiblings
(
walk
,
"cpu-unit"
))
!=
0
;
walk
=
prom_getsibling
(
walk
))
{
bbnode
=
prom_getchild
(
walk
);
if
(
bbnode
&&
(
bbnode
=
prom_searchsiblings
(
bbnode
,
"bootbus"
)))
{
if
((
zsnode
=
prom_getchild
(
bbnode
))
==
node
)
{
cpunode
=
walk
;
break
;
}
}
}
if
(
!
walk
)
{
prom_printf
(
"SunZilog: Cannot find the %d'th bootbus on sun4d.
\n
"
,
(
chip
/
2
));
prom_halt
();
}
if
(
prom_getproperty
(
zsnode
,
"reg"
,
(
char
*
)
zsreg
,
sizeof
(
zsreg
))
==
-
1
)
{
prom_printf
(
"SunZilog: Cannot map Zilog %d
\n
"
,
chip
);
prom_halt
();
}
/* XXX Looks like an off by one? */
prom_apply_generic_ranges
(
bbnode
,
cpunode
,
zsreg
,
1
);
res
.
start
=
zsreg
[
0
].
phys_addr
;
res
.
end
=
res
.
start
+
(
8
-
1
);
res
.
flags
=
zsreg
[
0
].
which_io
|
IORESOURCE_IO
;
mapped_addr
=
sbus_ioremap
(
&
res
,
0
,
8
,
"Zilog Serial"
);
}
else
{
zsnode
=
node
;
#if 0 /* XXX When was this used? */
if (prom_getintdefault(zsnode, "slave", -1) != chipid) {
zsnode = prom_getsibling(zsnode);
continue;
}
#endif
/*
* "address" is only present on ports that OBP opened
* (from Mitch Bradley's "Hitchhiker's Guide to OBP").
* We do not use it.
*/
if
(
prom_getproperty
(
zsnode
,
"reg"
,
(
char
*
)
zsreg
,
sizeof
(
zsreg
))
==
-
1
)
{
prom_printf
(
"SunZilog: Cannot map Zilog %d
\n
"
,
chip
);
prom_halt
();
}
if
(
sparc_cpu_model
==
sun4m
)
/* Crude. Pass parent. XXX */
prom_apply_obio_ranges
(
zsreg
,
1
);
res
.
start
=
zsreg
[
0
].
phys_addr
;
res
.
end
=
res
.
start
+
(
8
-
1
);
res
.
flags
=
zsreg
[
0
].
which_io
|
IORESOURCE_IO
;
mapped_addr
=
sbus_ioremap
(
&
res
,
0
,
8
,
"Zilog Serial"
);
}
if
(
prom_getproperty
(
zsnode
,
"intr"
,
(
char
*
)
irq_info
,
sizeof
(
irq_info
))
%
sizeof
(
struct
linux_prom_irqs
))
{
prom_printf
(
"SunZilog: Cannot get IRQ property for Zilog %d.
\n
"
,
chip
);
prom_halt
();
}
if
(
zilog_irq
==
-
1
)
{
zilog_irq
=
irq_info
[
0
].
pri
;
}
else
if
(
zilog_irq
!=
irq_info
[
0
].
pri
)
{
/* XXX. Dumb. Should handle per-chip IRQ, for add-ons. */
prom_printf
(
"SunZilog: Inconsistent IRQ layout for Zilog %d.
\n
"
,
chip
);
prom_halt
();
}
return
(
struct
zilog_layout
__iomem
*
)
mapped_addr
;
}
#endif
/* !(CONFIG_SPARC64) */
/* Get the address of the registers for SunZilog instance CHIP. */
static
struct
zilog_layout
__iomem
*
__init
get_zs
(
int
chip
,
int
node
)
{
if
(
chip
<
0
||
chip
>=
NUM_SUNZILOG
)
{
prom_printf
(
"SunZilog: Illegal chip number %d in get_zs.
\n
"
,
chip
);
prom_halt
();
}
#ifdef CONFIG_SPARC64
return
get_zs_sun4u
(
chip
,
node
);
#else
if
(
sparc_cpu_model
==
sun4
)
{
struct
resource
res
;
/* Not probe-able, hard code it. */
switch
(
chip
)
{
case
0
:
res
.
start
=
0xf1000000
;
break
;
case
1
:
res
.
start
=
0xf0000000
;
break
;
};
zilog_irq
=
12
;
res
.
end
=
(
res
.
start
+
(
8
-
1
));
res
.
flags
=
IORESOURCE_IO
;
return
sbus_ioremap
(
&
res
,
0
,
8
,
"SunZilog"
);
}
return
get_zs_sun4cmd
(
chip
,
node
);
#endif
kfree
(
sunzilog_port_table
);
sunzilog_irq_chain
=
NULL
;
kfree
(
sunzilog_chip_regs
);
}
#define ZS_PUT_CHAR_MAX_DELAY 2000
/* 10 ms */
...
...
@@ -1260,7 +1071,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
* udelay with ZSDELAY as that is a NOP on some platforms. -DaveM
*/
do
{
unsigned
char
val
=
sbus_
readb
(
&
channel
->
control
);
unsigned
char
val
=
readb
(
&
channel
->
control
);
if
(
val
&
Tx_BUF_EMP
)
{
ZSDELAY
();
break
;
...
...
@@ -1268,7 +1079,7 @@ static void sunzilog_putchar(struct uart_port *port, int ch)
udelay
(
5
);
}
while
(
--
loops
);
sbus_
writeb
(
ch
,
&
channel
->
data
);
writeb
(
ch
,
&
channel
->
data
);
ZSDELAY
();
ZS_WSYNC
(
channel
);
}
...
...
@@ -1385,28 +1196,6 @@ static struct console sunzilog_console = {
.
data
=
&
sunzilog_reg
,
};
static
int
__init
sunzilog_console_init
(
void
)
{
int
i
;
if
(
con_is_present
())
return
0
;
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
int
this_minor
=
sunzilog_reg
.
minor
+
i
;
if
((
this_minor
-
64
)
==
(
serial_console
-
1
))
break
;
}
if
(
i
==
NUM_CHANNELS
)
return
0
;
sunzilog_console
.
index
=
i
;
sunzilog_port_table
[
i
].
flags
|=
SUNZILOG_FLAG_IS_CONS
;
register_console
(
&
sunzilog_console
);
return
0
;
}
static
inline
struct
console
*
SUNZILOG_CONSOLE
(
void
)
{
int
i
;
...
...
@@ -1431,101 +1220,8 @@ static inline struct console *SUNZILOG_CONSOLE(void)
#else
#define SUNZILOG_CONSOLE() (NULL)
#define sunzilog_console_init() do { } while (0)
#endif
/*
* We scan the PROM tree recursively. This is the most reliable way
* to find Zilog nodes on various platforms. However, we face an extreme
* shortage of kernel stack, so we must be very careful. To that end,
* we scan only to a certain depth, and we use a common property buffer
* in the scan structure.
*/
#define ZS_PROPSIZE 128
#define ZS_SCAN_DEPTH 5
struct
zs_probe_scan
{
int
depth
;
void
(
*
scanner
)(
struct
zs_probe_scan
*
t
,
int
node
);
int
devices
;
char
prop
[
ZS_PROPSIZE
];
};
static
int
__inline__
sunzilog_node_ok
(
int
node
,
const
char
*
name
,
int
len
)
{
if
(
strncmp
(
name
,
"zs"
,
len
)
==
0
)
return
1
;
/* Don't fold this procedure just yet. Compare to su_node_ok(). */
return
0
;
}
static
void
__init
sunzilog_scan
(
struct
zs_probe_scan
*
t
,
int
node
)
{
int
len
;
for
(;
node
!=
0
;
node
=
prom_getsibling
(
node
))
{
len
=
prom_getproperty
(
node
,
"name"
,
t
->
prop
,
ZS_PROPSIZE
);
if
(
len
<=
1
)
continue
;
/* Broken PROM node */
if
(
sunzilog_node_ok
(
node
,
t
->
prop
,
len
))
{
(
*
t
->
scanner
)(
t
,
node
);
}
else
{
if
(
t
->
depth
<
ZS_SCAN_DEPTH
)
{
t
->
depth
++
;
sunzilog_scan
(
t
,
prom_getchild
(
node
));
--
t
->
depth
;
}
}
}
}
static
void
__init
sunzilog_prepare
(
void
)
{
struct
uart_sunzilog_port
*
up
;
struct
zilog_layout
__iomem
*
rp
;
int
channel
,
chip
;
/*
* Temporary fix.
*/
for
(
channel
=
0
;
channel
<
NUM_CHANNELS
;
channel
++
)
spin_lock_init
(
&
sunzilog_port_table
[
channel
].
port
.
lock
);
sunzilog_irq_chain
=
up
=
&
sunzilog_port_table
[
0
];
for
(
channel
=
0
;
channel
<
NUM_CHANNELS
-
1
;
channel
++
)
up
[
channel
].
next
=
&
up
[
channel
+
1
];
up
[
channel
].
next
=
NULL
;
for
(
chip
=
0
;
chip
<
NUM_SUNZILOG
;
chip
++
)
{
rp
=
sunzilog_chip_regs
[
chip
];
up
[(
chip
*
2
)
+
0
].
port
.
membase
=
(
void
__iomem
*
)
&
rp
->
channelA
;
up
[(
chip
*
2
)
+
1
].
port
.
membase
=
(
void
__iomem
*
)
&
rp
->
channelB
;
/* Channel A */
up
[(
chip
*
2
)
+
0
].
port
.
iotype
=
UPIO_MEM
;
up
[(
chip
*
2
)
+
0
].
port
.
irq
=
zilog_irq
;
up
[(
chip
*
2
)
+
0
].
port
.
uartclk
=
ZS_CLOCK
;
up
[(
chip
*
2
)
+
0
].
port
.
fifosize
=
1
;
up
[(
chip
*
2
)
+
0
].
port
.
ops
=
&
sunzilog_pops
;
up
[(
chip
*
2
)
+
0
].
port
.
type
=
PORT_SUNZILOG
;
up
[(
chip
*
2
)
+
0
].
port
.
flags
=
0
;
up
[(
chip
*
2
)
+
0
].
port
.
line
=
(
chip
*
2
)
+
0
;
up
[(
chip
*
2
)
+
0
].
flags
|=
SUNZILOG_FLAG_IS_CHANNEL_A
;
/* Channel B */
up
[(
chip
*
2
)
+
1
].
port
.
iotype
=
UPIO_MEM
;
up
[(
chip
*
2
)
+
1
].
port
.
irq
=
zilog_irq
;
up
[(
chip
*
2
)
+
1
].
port
.
uartclk
=
ZS_CLOCK
;
up
[(
chip
*
2
)
+
1
].
port
.
fifosize
=
1
;
up
[(
chip
*
2
)
+
1
].
port
.
ops
=
&
sunzilog_pops
;
up
[(
chip
*
2
)
+
1
].
port
.
type
=
PORT_SUNZILOG
;
up
[(
chip
*
2
)
+
1
].
port
.
flags
=
0
;
up
[(
chip
*
2
)
+
1
].
port
.
line
=
(
chip
*
2
)
+
1
;
up
[(
chip
*
2
)
+
1
].
flags
|=
0
;
}
}
static
void
__init
sunzilog_init_kbdms
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
{
int
baud
,
brg
;
...
...
@@ -1539,8 +1235,6 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
up
->
cflag
=
B4800
|
CS8
|
CLOCAL
|
CREAD
;
baud
=
4800
;
}
printk
(
KERN_INFO
"zs%d at 0x%p (irq = %d) is a SunZilog
\n
"
,
channel
,
up
->
port
.
membase
,
zilog_irq
);
up
->
curregs
[
R15
]
=
BRKIE
;
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
...
...
@@ -1552,216 +1246,253 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
#ifdef CONFIG_SERIO
static
void
__init
sunzilog_register_serio
(
struct
uart_sunzilog_port
*
up
,
int
channel
)
{
struct
serio
*
serio
;
up
->
serio
=
serio
=
kmalloc
(
sizeof
(
struct
serio
),
GFP_KERNEL
);
if
(
serio
)
{
memset
(
serio
,
0
,
sizeof
(
*
serio
));
struct
serio
*
serio
=
&
up
->
serio
;
serio
->
port_data
=
up
;
serio
->
port_data
=
up
;
serio
->
id
.
type
=
SERIO_RS232
;
if
(
channel
==
KEYBOARD_LINE
)
{
serio
->
id
.
proto
=
SERIO_SUNKBD
;
strlcpy
(
serio
->
name
,
"zskbd"
,
sizeof
(
serio
->
name
));
}
else
{
serio
->
id
.
proto
=
SERIO_SUN
;
serio
->
id
.
extra
=
1
;
strlcpy
(
serio
->
name
,
"zsms"
,
sizeof
(
serio
->
name
));
}
strlcpy
(
serio
->
phys
,
(
channel
==
KEYBOARD_LINE
?
"zs/serio0"
:
"zs/serio1"
),
sizeof
(
serio
->
phys
));
serio
->
write
=
sunzilog_serio_write
;
serio
->
open
=
sunzilog_serio_open
;
serio
->
close
=
sunzilog_serio_close
;
serio_register_port
(
serio
);
serio
->
id
.
type
=
SERIO_RS232
;
if
(
channel
==
KEYBOARD_LINE
)
{
serio
->
id
.
proto
=
SERIO_SUNKBD
;
strlcpy
(
serio
->
name
,
"zskbd"
,
sizeof
(
serio
->
name
));
}
else
{
printk
(
KERN_WARNING
"zs%d: not enough memory for serio port
\n
"
,
channel
);
serio
->
id
.
proto
=
SERIO_SUN
;
serio
->
id
.
extra
=
1
;
strlcpy
(
serio
->
name
,
"zsms"
,
sizeof
(
serio
->
name
));
}
strlcpy
(
serio
->
phys
,
(
channel
==
KEYBOARD_LINE
?
"zs/serio0"
:
"zs/serio1"
),
sizeof
(
serio
->
phys
));
serio
->
write
=
sunzilog_serio_write
;
serio
->
open
=
sunzilog_serio_open
;
serio
->
close
=
sunzilog_serio_close
;
serio
->
dev
.
parent
=
up
->
port
.
dev
;
serio_register_port
(
serio
);
}
#endif
static
void
__init
sunzilog_init_hw
(
void
)
static
void
__init
sunzilog_init_hw
(
struct
uart_sunzilog_port
*
up
)
{
int
i
;
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
struct
uart_sunzilog_port
*
up
=
&
sunzilog_port_table
[
i
];
struct
zilog_channel
__iomem
*
channel
=
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
);
unsigned
long
flags
;
int
baud
,
brg
;
struct
zilog_channel
__iomem
*
channel
;
unsigned
long
flags
;
int
baud
,
brg
;
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
channel
=
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
);
if
(
ZS_IS_CHANNEL_A
(
up
))
{
write_zsreg
(
channel
,
R9
,
FHWRES
);
ZSDELAY_LONG
();
(
void
)
read_zsreg
(
channel
,
R0
);
}
spin_lock_irqsave
(
&
up
->
port
.
lock
,
flags
);
if
(
ZS_IS_CHANNEL_A
(
up
))
{
write_zsreg
(
channel
,
R9
,
FHWRES
);
ZSDELAY_LONG
();
(
void
)
read_zsreg
(
channel
,
R0
);
}
if
(
i
==
KEYBOARD_LINE
||
i
==
MOUSE_LINE
)
{
sunzilog_init_kbdms
(
up
,
i
);
up
->
curregs
[
R9
]
|=
(
NV
|
MIE
);
write_zsreg
(
channel
,
R9
,
up
->
curregs
[
R9
]);
}
else
{
/* Normal serial TTY. */
up
->
parity_mask
=
0xff
;
up
->
curregs
[
R1
]
=
EXT_INT_ENAB
|
INT_ALL_Rx
|
TxINT_ENAB
;
up
->
curregs
[
R4
]
=
PAR_EVEN
|
X16CLK
|
SB1
;
up
->
curregs
[
R3
]
=
RxENAB
|
Rx8
;
up
->
curregs
[
R5
]
=
TxENAB
|
Tx8
;
up
->
curregs
[
R9
]
=
NV
|
MIE
;
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
R11
]
=
TCBR
|
RCBR
;
baud
=
9600
;
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R14
]
=
BRSRC
|
BRENAB
;
__load_zsregs
(
channel
,
up
->
curregs
);
write_zsreg
(
channel
,
R9
,
up
->
curregs
[
R9
]);
}
if
(
up
->
port
.
line
==
KEYBOARD_LINE
||
up
->
port
.
line
==
MOUSE_LINE
)
{
sunzilog_init_kbdms
(
up
,
up
->
port
.
line
);
up
->
curregs
[
R9
]
|=
(
NV
|
MIE
);
write_zsreg
(
channel
,
R9
,
up
->
curregs
[
R9
]);
}
else
{
/* Normal serial TTY. */
up
->
parity_mask
=
0xff
;
up
->
curregs
[
R1
]
=
EXT_INT_ENAB
|
INT_ALL_Rx
|
TxINT_ENAB
;
up
->
curregs
[
R4
]
=
PAR_EVEN
|
X16CLK
|
SB1
;
up
->
curregs
[
R3
]
=
RxENAB
|
Rx8
;
up
->
curregs
[
R5
]
=
TxENAB
|
Tx8
;
up
->
curregs
[
R9
]
=
NV
|
MIE
;
up
->
curregs
[
R10
]
=
NRZ
;
up
->
curregs
[
R11
]
=
TCBR
|
RCBR
;
baud
=
9600
;
brg
=
BPS_TO_BRG
(
baud
,
ZS_CLOCK
/
ZS_CLOCK_DIVISOR
);
up
->
curregs
[
R12
]
=
(
brg
&
0xff
);
up
->
curregs
[
R13
]
=
(
brg
>>
8
)
&
0xff
;
up
->
curregs
[
R14
]
=
BRSRC
|
BRENAB
;
__load_zsregs
(
channel
,
up
->
curregs
);
write_zsreg
(
channel
,
R9
,
up
->
curregs
[
R9
]);
}
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
spin_unlock_irqrestore
(
&
up
->
port
.
lock
,
flags
);
#ifdef CONFIG_SERIO
if
(
i
==
KEYBOARD_LINE
||
i
==
MOUSE_LINE
)
sunzilog_register_serio
(
up
,
i
);
if
(
up
->
port
.
line
==
KEYBOARD_LINE
||
up
->
port
.
line
==
MOUSE_LINE
)
sunzilog_register_serio
(
up
,
up
->
port
.
line
);
#endif
}
}
static
struct
zilog_layout
__iomem
*
__init
get_zs
(
int
chip
,
int
node
);
static
void
__init
sunzilog_scan_probe
(
struct
zs_probe_scan
*
t
,
int
node
)
{
sunzilog_chip_regs
[
t
->
devices
]
=
get_zs
(
t
->
devices
,
node
);
t
->
devices
++
;
}
static
int
__
init
sunzilog_ports_init
(
void
)
static
int
__
devinit
zs_get_instance
(
struct
device_node
*
dp
)
{
struct
zs_probe_scan
scan
;
int
ret
;
int
uart_count
;
int
i
;
printk
(
KERN_DEBUG
"SunZilog: %d chips.
\n
"
,
NUM_SUNZILOG
);
ret
=
of_getintprop_default
(
dp
,
"slave"
,
-
1
);
if
(
ret
!=
-
1
)
return
ret
;
scan
.
scanner
=
sunzilog_scan_probe
;
scan
.
depth
=
0
;
scan
.
devices
=
0
;
sunzilog_scan
(
&
scan
,
prom_getchild
(
prom_root_node
))
;
if
(
of_find_property
(
dp
,
"keyboard"
,
NULL
))
ret
=
1
;
else
ret
=
0
;
sunzilog_prepare
();
return
ret
;
}
if
(
request_irq
(
zilog_irq
,
sunzilog_interrupt
,
SA_SHIRQ
,
"SunZilog"
,
sunzilog_irq_chain
))
{
prom_printf
(
"SunZilog: Unable to register zs interrupt handler.
\n
"
);
prom_halt
();
}
static
int
__devinit
zs_probe
(
struct
of_device
*
dev
,
const
struct
of_device_id
*
match
)
{
static
int
zilog_irq
=
-
1
;
struct
of_device
*
op
=
to_of_device
(
&
dev
->
dev
);
struct
uart_sunzilog_port
*
up
;
struct
zilog_layout
__iomem
*
rp
;
int
inst
=
zs_get_instance
(
dev
->
node
);
int
err
;
sunzilog_init_hw
();
sunzilog_chip_regs
[
inst
]
=
of_ioremap
(
&
op
->
resource
[
0
],
0
,
sizeof
(
struct
zilog_layout
),
"zs"
);
if
(
!
sunzilog_chip_regs
[
inst
])
return
-
ENOMEM
;
/* We can only init this once we have probed the Zilogs
* in the system. Do not count channels assigned to keyboards
* or mice when we are deciding how many ports to register.
*/
uart_count
=
0
;
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
struct
uart_sunzilog_port
*
up
=
&
sunzilog_port_table
[
i
];
rp
=
sunzilog_chip_regs
[
inst
];
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
continue
;
if
(
zilog_irq
==
-
1
)
{
zilog_irq
=
op
->
irqs
[
0
];
err
=
request_irq
(
zilog_irq
,
sunzilog_interrupt
,
SA_SHIRQ
,
"zs"
,
sunzilog_irq_chain
);
if
(
err
)
{
of_iounmap
(
rp
,
sizeof
(
struct
zilog_layout
));
uart_count
++
;
return
err
;
}
}
sunzilog_reg
.
nr
=
uart_count
;
sunzilog_reg
.
minor
=
sunserial_current_minor
;
ret
=
uart_register_driver
(
&
sunzilog_reg
);
if
(
ret
==
0
)
{
sunzilog_reg
.
tty_driver
->
name_base
=
sunzilog_reg
.
minor
-
64
;
sunzilog_reg
.
cons
=
SUNZILOG_CONSOLE
();
sunserial_current_minor
+=
uart_count
;
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
struct
uart_sunzilog_port
*
up
=
&
sunzilog_port_table
[
i
];
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
continue
;
if
(
uart_add_one_port
(
&
sunzilog_reg
,
&
up
->
port
))
{
printk
(
KERN_ERR
"SunZilog: failed to add port zs%d
\n
"
,
i
);
}
up
=
&
sunzilog_port_table
[
inst
*
2
];
/* Channel A */
up
[
0
].
port
.
mapbase
=
op
->
resource
[
0
].
start
+
0x00
;
up
[
0
].
port
.
membase
=
(
void
__iomem
*
)
&
rp
->
channelA
;
up
[
0
].
port
.
iotype
=
UPIO_MEM
;
up
[
0
].
port
.
irq
=
op
->
irqs
[
0
];
up
[
0
].
port
.
uartclk
=
ZS_CLOCK
;
up
[
0
].
port
.
fifosize
=
1
;
up
[
0
].
port
.
ops
=
&
sunzilog_pops
;
up
[
0
].
port
.
type
=
PORT_SUNZILOG
;
up
[
0
].
port
.
flags
=
0
;
up
[
0
].
port
.
line
=
(
inst
*
2
)
+
0
;
up
[
0
].
port
.
dev
=
&
op
->
dev
;
up
[
0
].
flags
|=
SUNZILOG_FLAG_IS_CHANNEL_A
;
if
(
inst
==
1
)
up
[
0
].
flags
|=
SUNZILOG_FLAG_CONS_KEYB
;
sunzilog_init_hw
(
&
up
[
0
]);
/* Channel B */
up
[
1
].
port
.
mapbase
=
op
->
resource
[
0
].
start
+
0x04
;
up
[
1
].
port
.
membase
=
(
void
__iomem
*
)
&
rp
->
channelB
;
up
[
1
].
port
.
iotype
=
UPIO_MEM
;
up
[
1
].
port
.
irq
=
op
->
irqs
[
0
];
up
[
1
].
port
.
uartclk
=
ZS_CLOCK
;
up
[
1
].
port
.
fifosize
=
1
;
up
[
1
].
port
.
ops
=
&
sunzilog_pops
;
up
[
1
].
port
.
type
=
PORT_SUNZILOG
;
up
[
1
].
port
.
flags
=
0
;
up
[
1
].
port
.
line
=
(
inst
*
2
)
+
1
;
up
[
1
].
port
.
dev
=
&
op
->
dev
;
up
[
1
].
flags
|=
0
;
if
(
inst
==
1
)
up
[
1
].
flags
|=
SUNZILOG_FLAG_CONS_MOUSE
;
sunzilog_init_hw
(
&
up
[
1
]);
if
(
inst
!=
1
)
{
err
=
uart_add_one_port
(
&
sunzilog_reg
,
&
up
[
0
].
port
);
if
(
err
)
{
of_iounmap
(
rp
,
sizeof
(
struct
zilog_layout
));
return
err
;
}
err
=
uart_add_one_port
(
&
sunzilog_reg
,
&
up
[
1
].
port
);
if
(
err
)
{
uart_remove_one_port
(
&
sunzilog_reg
,
&
up
[
0
].
port
);
of_iounmap
(
rp
,
sizeof
(
struct
zilog_layout
));
return
err
;
}
}
return
ret
;
}
static
void
__init
sunzilog_scan_count
(
struct
zs_probe_scan
*
t
,
int
node
)
{
t
->
devices
++
;
return
0
;
}
static
int
__
init
sunzilog_ports_count
(
void
)
static
int
__
devexit
zs_remove
(
struct
of_device
*
dev
)
{
struct
zs_probe_scan
scan
;
struct
uart_sunzilog_port
*
up
=
dev_get_drvdata
(
&
dev
->
dev
);
struct
zilog_channel
__iomem
*
channel
;
/* Sun4 Zilog setup is hard coded, no probing to do. */
if
(
sparc_cpu_model
==
sun4
)
return
2
;
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
{
#ifdef CONFIG_SERIO
serio_unregister_port
(
&
up
->
serio
);
#endif
}
else
uart_remove_one_port
(
&
sunzilog_reg
,
&
up
->
port
);
scan
.
scanner
=
sunzilog_scan_count
;
scan
.
depth
=
0
;
scan
.
devices
=
0
;
channel
=
ZILOG_CHANNEL_FROM_PORT
(
&
up
->
port
);
sunzilog_scan
(
&
scan
,
prom_getchild
(
prom_root_node
));
of_iounmap
(
channel
,
sizeof
(
struct
zilog_channel
));
return
scan
.
devices
;
return
0
;
}
static
struct
of_device_id
zs_match
[]
=
{
{
.
name
=
"zs"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
zs_match
);
static
struct
of_platform_driver
zs_driver
=
{
.
name
=
"zs"
,
.
match_table
=
zs_match
,
.
probe
=
zs_probe
,
.
remove
=
__devexit_p
(
zs_remove
),
};
static
int
__init
sunzilog_init
(
void
)
{
struct
device_node
*
dp
;
int
err
;
NUM_SUNZILOG
=
sunzilog_ports_count
()
;
if
(
NUM_SUNZILOG
==
0
)
return
-
ENODEV
;
NUM_SUNZILOG
=
0
;
for_each_node_by_name
(
dp
,
"zs"
)
NUM_SUNZILOG
++
;
sunzilog_alloc_tables
();
if
(
NUM_SUNZILOG
)
{
int
uart_count
;
sunzilog_ports_init
();
err
=
sunzilog_alloc_tables
();
if
(
err
)
return
err
;
return
0
;
/* Subtract 1 for keyboard, 1 for mouse. */
uart_count
=
(
NUM_SUNZILOG
*
2
)
-
2
;
sunzilog_reg
.
nr
=
uart_count
;
sunzilog_reg
.
minor
=
sunserial_current_minor
;
err
=
uart_register_driver
(
&
sunzilog_reg
);
if
(
err
)
{
sunzilog_free_tables
();
return
err
;
}
sunzilog_reg
.
tty_driver
->
name_base
=
sunzilog_reg
.
minor
-
64
;
sunzilog_reg
.
cons
=
SUNZILOG_CONSOLE
();
sunserial_current_minor
+=
uart_count
;
}
return
of_register_driver
(
&
zs_driver
,
&
of_bus_type
);
}
static
void
__exit
sunzilog_exit
(
void
)
{
int
i
;
of_unregister_driver
(
&
zs_driver
)
;
for
(
i
=
0
;
i
<
NUM_CHANNELS
;
i
++
)
{
struct
uart_sunzilog_port
*
up
=
&
sunzilog_port_table
[
i
];
if
(
ZS_IS_KEYB
(
up
)
||
ZS_IS_MOUSE
(
up
))
{
#ifdef CONFIG_SERIO
if
(
up
->
serio
)
{
serio_unregister_port
(
up
->
serio
);
up
->
serio
=
NULL
;
}
#endif
}
else
uart_remove_one_port
(
&
sunzilog_reg
,
&
up
->
port
);
if
(
NUM_SUNZILOG
)
{
uart_unregister_driver
(
&
sunzilog_reg
);
sunzilog_free_tables
();
}
uart_unregister_driver
(
&
sunzilog_reg
);
}
module_init
(
sunzilog_init
);
...
...
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