forked from Minki/linux
tty/serial/pmac_zilog: Fix suspend & resume
This patch reworks & simplifies pmac_zilog handling of suspend/resume, essentially removing all the specific code in there and using the generic uart helpers. This required properly registering the tty as a child of the macio (or platform) device, so I had to delay the registration a bit (we used to register the ports very very early). We still register the kernel console early though. I removed a couple of unused or useless flags as well, relying on the core to not call us when asleep. I also removed the essentially useless interrupt mutex, simplifying the locking a bit. I removed some code for handling unexpected interrupt which should never be hit and could potentially be harmful (causing us to access a register on a powered off SCC). We diable port interrupts on close always so there should be no need to drain data on a closed port. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
43ca5d347a
commit
a79dd5ae5a
@ -99,6 +99,9 @@ MODULE_LICENSE("GPL");
|
|||||||
#define PMACZILOG_NAME "ttyPZ"
|
#define PMACZILOG_NAME "ttyPZ"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define pmz_debug(fmt, arg...) pr_debug("ttyPZ%d: " fmt, uap->port.line, ## arg)
|
||||||
|
#define pmz_error(fmt, arg...) pr_err("ttyPZ%d: " fmt, uap->port.line, ## arg)
|
||||||
|
#define pmz_info(fmt, arg...) pr_info("ttyPZ%d: " fmt, uap->port.line, ## arg)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the sake of early serial console, we can do a pre-probe
|
* For the sake of early serial console, we can do a pre-probe
|
||||||
@ -106,7 +109,6 @@ MODULE_LICENSE("GPL");
|
|||||||
*/
|
*/
|
||||||
static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
|
static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
|
||||||
static int pmz_ports_count;
|
static int pmz_ports_count;
|
||||||
static DEFINE_MUTEX(pmz_irq_mutex);
|
|
||||||
|
|
||||||
static struct uart_driver pmz_uart_reg = {
|
static struct uart_driver pmz_uart_reg = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
@ -126,9 +128,6 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Let pending transmits finish. */
|
/* Let pending transmits finish. */
|
||||||
for (i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
unsigned char stat = read_zsreg(uap, R1);
|
unsigned char stat = read_zsreg(uap, R1);
|
||||||
@ -234,26 +233,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
|
|||||||
unsigned char ch, r1, drop, error, flag;
|
unsigned char ch, r1, drop, error, flag;
|
||||||
int loops = 0;
|
int loops = 0;
|
||||||
|
|
||||||
/* The interrupt can be enabled when the port isn't open, typically
|
|
||||||
* that happens when using one port is open and the other closed (stale
|
|
||||||
* interrupt) or when one port is used as a console.
|
|
||||||
*/
|
|
||||||
if (!ZS_IS_OPEN(uap)) {
|
|
||||||
pmz_debug("pmz: draining input\n");
|
|
||||||
/* Port is closed, drain input data */
|
|
||||||
for (;;) {
|
|
||||||
if ((++loops) > 1000)
|
|
||||||
goto flood;
|
|
||||||
(void)read_zsreg(uap, R1);
|
|
||||||
write_zsreg(uap, R0, ERR_RES);
|
|
||||||
(void)read_zsdata(uap);
|
|
||||||
ch = read_zsreg(uap, R0);
|
|
||||||
if (!(ch & Rx_CH_AV))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check, make sure the old bug is no longer happening */
|
/* Sanity check, make sure the old bug is no longer happening */
|
||||||
if (uap->port.state == NULL || uap->port.state->port.tty == NULL) {
|
if (uap->port.state == NULL || uap->port.state->port.tty == NULL) {
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
@ -393,8 +372,6 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
|
|||||||
{
|
{
|
||||||
struct circ_buf *xmit;
|
struct circ_buf *xmit;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
if (ZS_IS_CONS(uap)) {
|
if (ZS_IS_CONS(uap)) {
|
||||||
unsigned char status = read_zsreg(uap, R0);
|
unsigned char status = read_zsreg(uap, R0);
|
||||||
|
|
||||||
@ -491,6 +468,10 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
|
|||||||
/* Channel A */
|
/* Channel A */
|
||||||
tty = NULL;
|
tty = NULL;
|
||||||
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
|
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
|
||||||
|
if (!ZS_IS_OPEN(uap_a)) {
|
||||||
|
pmz_debug("ChanA interrupt while open !\n");
|
||||||
|
goto skip_a;
|
||||||
|
}
|
||||||
write_zsreg(uap_a, R0, RES_H_IUS);
|
write_zsreg(uap_a, R0, RES_H_IUS);
|
||||||
zssync(uap_a);
|
zssync(uap_a);
|
||||||
if (r3 & CHAEXT)
|
if (r3 & CHAEXT)
|
||||||
@ -501,16 +482,21 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
|
|||||||
pmz_transmit_chars(uap_a);
|
pmz_transmit_chars(uap_a);
|
||||||
rc = IRQ_HANDLED;
|
rc = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
skip_a:
|
||||||
spin_unlock(&uap_a->port.lock);
|
spin_unlock(&uap_a->port.lock);
|
||||||
if (tty != NULL)
|
if (tty != NULL)
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
|
|
||||||
if (uap_b->node == NULL)
|
if (!uap_b)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock(&uap_b->port.lock);
|
spin_lock(&uap_b->port.lock);
|
||||||
tty = NULL;
|
tty = NULL;
|
||||||
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
|
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
|
||||||
|
if (!ZS_IS_OPEN(uap_a)) {
|
||||||
|
pmz_debug("ChanB interrupt while open !\n");
|
||||||
|
goto skip_b;
|
||||||
|
}
|
||||||
write_zsreg(uap_b, R0, RES_H_IUS);
|
write_zsreg(uap_b, R0, RES_H_IUS);
|
||||||
zssync(uap_b);
|
zssync(uap_b);
|
||||||
if (r3 & CHBEXT)
|
if (r3 & CHBEXT)
|
||||||
@ -521,14 +507,12 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
|
|||||||
pmz_transmit_chars(uap_b);
|
pmz_transmit_chars(uap_b);
|
||||||
rc = IRQ_HANDLED;
|
rc = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
skip_b:
|
||||||
spin_unlock(&uap_b->port.lock);
|
spin_unlock(&uap_b->port.lock);
|
||||||
if (tty != NULL)
|
if (tty != NULL)
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
#ifdef DEBUG_HARD
|
|
||||||
pmz_debug("irq done.\n");
|
|
||||||
#endif
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,12 +537,8 @@ static inline u8 pmz_peek_status(struct uart_pmac_port *uap)
|
|||||||
*/
|
*/
|
||||||
static unsigned int pmz_tx_empty(struct uart_port *port)
|
static unsigned int pmz_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_pmac_port *uap = to_pmz(port);
|
|
||||||
unsigned char status;
|
unsigned char status;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
|
|
||||||
return TIOCSER_TEMT;
|
|
||||||
|
|
||||||
status = pmz_peek_status(to_pmz(port));
|
status = pmz_peek_status(to_pmz(port));
|
||||||
if (status & Tx_BUF_EMP)
|
if (status & Tx_BUF_EMP)
|
||||||
return TIOCSER_TEMT;
|
return TIOCSER_TEMT;
|
||||||
@ -580,8 +560,7 @@ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||||||
if (ZS_IS_IRDA(uap))
|
if (ZS_IS_IRDA(uap))
|
||||||
return;
|
return;
|
||||||
/* We get called during boot with a port not up yet */
|
/* We get called during boot with a port not up yet */
|
||||||
if (ZS_IS_ASLEEP(uap) ||
|
if (!(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)))
|
||||||
!(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_bits = clear_bits = 0;
|
set_bits = clear_bits = 0;
|
||||||
@ -600,8 +579,7 @@ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||||||
/* NOTE: Not subject to 'transmitter active' rule. */
|
/* NOTE: Not subject to 'transmitter active' rule. */
|
||||||
uap->curregs[R5] |= set_bits;
|
uap->curregs[R5] |= set_bits;
|
||||||
uap->curregs[R5] &= ~clear_bits;
|
uap->curregs[R5] &= ~clear_bits;
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
write_zsreg(uap, R5, uap->curregs[R5]);
|
write_zsreg(uap, R5, uap->curregs[R5]);
|
||||||
pmz_debug("pmz_set_mctrl: set bits: %x, clear bits: %x -> %x\n",
|
pmz_debug("pmz_set_mctrl: set bits: %x, clear bits: %x -> %x\n",
|
||||||
set_bits, clear_bits, uap->curregs[R5]);
|
set_bits, clear_bits, uap->curregs[R5]);
|
||||||
@ -619,9 +597,6 @@ static unsigned int pmz_get_mctrl(struct uart_port *port)
|
|||||||
unsigned char status;
|
unsigned char status;
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
status = read_zsreg(uap, R0);
|
status = read_zsreg(uap, R0);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -659,9 +634,6 @@ static void pmz_start_tx(struct uart_port *port)
|
|||||||
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
|
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
|
||||||
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
|
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
status = read_zsreg(uap, R0);
|
status = read_zsreg(uap, R0);
|
||||||
|
|
||||||
/* TX busy? Just wait for the TX done interrupt. */
|
/* TX busy? Just wait for the TX done interrupt. */
|
||||||
@ -700,9 +672,6 @@ static void pmz_stop_rx(struct uart_port *port)
|
|||||||
{
|
{
|
||||||
struct uart_pmac_port *uap = to_pmz(port);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pmz_debug("pmz: stop_rx()()\n");
|
pmz_debug("pmz: stop_rx()()\n");
|
||||||
|
|
||||||
/* Disable all RX interrupts. */
|
/* Disable all RX interrupts. */
|
||||||
@ -721,14 +690,12 @@ static void pmz_enable_ms(struct uart_port *port)
|
|||||||
struct uart_pmac_port *uap = to_pmz(port);
|
struct uart_pmac_port *uap = to_pmz(port);
|
||||||
unsigned char new_reg;
|
unsigned char new_reg;
|
||||||
|
|
||||||
if (ZS_IS_IRDA(uap) || uap->node == NULL)
|
if (ZS_IS_IRDA(uap))
|
||||||
return;
|
return;
|
||||||
new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
|
new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
|
||||||
if (new_reg != uap->curregs[R15]) {
|
if (new_reg != uap->curregs[R15]) {
|
||||||
uap->curregs[R15] = new_reg;
|
uap->curregs[R15] = new_reg;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
/* NOTE: Not subject to 'transmitter active' rule. */
|
/* NOTE: Not subject to 'transmitter active' rule. */
|
||||||
write_zsreg(uap, R15, uap->curregs[R15]);
|
write_zsreg(uap, R15, uap->curregs[R15]);
|
||||||
}
|
}
|
||||||
@ -744,8 +711,6 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)
|
|||||||
unsigned char set_bits, clear_bits, new_reg;
|
unsigned char set_bits, clear_bits, new_reg;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (uap->node == NULL)
|
|
||||||
return;
|
|
||||||
set_bits = clear_bits = 0;
|
set_bits = clear_bits = 0;
|
||||||
|
|
||||||
if (break_state)
|
if (break_state)
|
||||||
@ -758,12 +723,6 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)
|
|||||||
new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits;
|
new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits;
|
||||||
if (new_reg != uap->curregs[R5]) {
|
if (new_reg != uap->curregs[R5]) {
|
||||||
uap->curregs[R5] = new_reg;
|
uap->curregs[R5] = new_reg;
|
||||||
|
|
||||||
/* NOTE: Not subject to 'transmitter active' rule. */
|
|
||||||
if (ZS_IS_ASLEEP(uap)) {
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
write_zsreg(uap, R5, uap->curregs[R5]);
|
write_zsreg(uap, R5, uap->curregs[R5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -937,14 +896,21 @@ static int __pmz_startup(struct uart_pmac_port *uap)
|
|||||||
|
|
||||||
static void pmz_irda_reset(struct uart_pmac_port *uap)
|
static void pmz_irda_reset(struct uart_pmac_port *uap)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&uap->port.lock, flags);
|
||||||
uap->curregs[R5] |= DTR;
|
uap->curregs[R5] |= DTR;
|
||||||
write_zsreg(uap, R5, uap->curregs[R5]);
|
write_zsreg(uap, R5, uap->curregs[R5]);
|
||||||
zssync(uap);
|
zssync(uap);
|
||||||
mdelay(110);
|
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||||
|
msleep(110);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&uap->port.lock, flags);
|
||||||
uap->curregs[R5] &= ~DTR;
|
uap->curregs[R5] &= ~DTR;
|
||||||
write_zsreg(uap, R5, uap->curregs[R5]);
|
write_zsreg(uap, R5, uap->curregs[R5]);
|
||||||
zssync(uap);
|
zssync(uap);
|
||||||
mdelay(10);
|
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||||
|
msleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -959,13 +925,6 @@ static int pmz_startup(struct uart_port *port)
|
|||||||
|
|
||||||
pmz_debug("pmz: startup()\n");
|
pmz_debug("pmz: startup()\n");
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return -EAGAIN;
|
|
||||||
if (uap->node == NULL)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
mutex_lock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
|
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
|
||||||
|
|
||||||
/* A console is never powered down. Else, power up and
|
/* A console is never powered down. Else, power up and
|
||||||
@ -976,18 +935,14 @@ static int pmz_startup(struct uart_port *port)
|
|||||||
pwr_delay = __pmz_startup(uap);
|
pwr_delay = __pmz_startup(uap);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
sprintf(uap->irq_name, PMACZILOG_NAME"%d", uap->port.line);
|
||||||
pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
|
|
||||||
if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
|
if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
|
||||||
"SCC", uap)) {
|
uap->irq_name, uap)) {
|
||||||
pmz_error("Unable to register zs interrupt handler.\n");
|
pmz_error("Unable to register zs interrupt handler.\n");
|
||||||
pmz_set_scc_power(uap, 0);
|
pmz_set_scc_power(uap, 0);
|
||||||
mutex_unlock(&pmz_irq_mutex);
|
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
/* Right now, we deal with delay by blocking here, I'll be
|
/* Right now, we deal with delay by blocking here, I'll be
|
||||||
* smarter later on
|
* smarter later on
|
||||||
*/
|
*/
|
||||||
@ -1017,26 +972,19 @@ static void pmz_shutdown(struct uart_port *port)
|
|||||||
|
|
||||||
pmz_debug("pmz: shutdown()\n");
|
pmz_debug("pmz: shutdown()\n");
|
||||||
|
|
||||||
if (uap->node == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mutex_lock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
|
||||||
if (!ZS_IS_ASLEEP(uap)) {
|
/* Disable interrupt requests for the channel */
|
||||||
/* Disable interrupt requests for the channel */
|
pmz_interrupt_control(uap, 0);
|
||||||
pmz_interrupt_control(uap, 0);
|
|
||||||
|
|
||||||
if (!ZS_IS_CONS(uap)) {
|
if (!ZS_IS_CONS(uap)) {
|
||||||
/* Disable receiver and transmitter */
|
/* Disable receiver and transmitter */
|
||||||
uap->curregs[R3] &= ~RxENABLE;
|
uap->curregs[R3] &= ~RxENABLE;
|
||||||
uap->curregs[R5] &= ~TxENABLE;
|
uap->curregs[R5] &= ~TxENABLE;
|
||||||
|
|
||||||
/* Disable break assertion */
|
/* Disable break assertion */
|
||||||
uap->curregs[R5] &= ~SND_BRK;
|
uap->curregs[R5] &= ~SND_BRK;
|
||||||
pmz_maybe_update_regs(uap);
|
pmz_maybe_update_regs(uap);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
@ -1048,16 +996,11 @@ static void pmz_shutdown(struct uart_port *port)
|
|||||||
|
|
||||||
uap->flags &= ~PMACZILOG_FLAG_IS_OPEN;
|
uap->flags &= ~PMACZILOG_FLAG_IS_OPEN;
|
||||||
|
|
||||||
if (!ZS_IS_OPEN(uap->mate))
|
if (!ZS_IS_CONS(uap))
|
||||||
pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
|
|
||||||
|
|
||||||
if (!ZS_IS_ASLEEP(uap) && !ZS_IS_CONS(uap))
|
|
||||||
pmz_set_scc_power(uap, 0); /* Shut the chip down */
|
pmz_set_scc_power(uap, 0); /* Shut the chip down */
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
mutex_unlock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
pmz_debug("pmz: shutdown() done.\n");
|
pmz_debug("pmz: shutdown() done.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1305,9 +1248,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||||||
|
|
||||||
pmz_debug("pmz: set_termios()\n");
|
pmz_debug("pmz: set_termios()\n");
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
|
memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
|
||||||
|
|
||||||
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
|
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
|
||||||
@ -1605,25 +1545,34 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
|
|||||||
*/
|
*/
|
||||||
static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
||||||
{
|
{
|
||||||
|
struct uart_pmac_port *uap;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Iterate the pmz_ports array to find a matching entry
|
/* Iterate the pmz_ports array to find a matching entry
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < MAX_ZS_PORTS; i++)
|
for (i = 0; i < MAX_ZS_PORTS; i++)
|
||||||
if (pmz_ports[i].node == mdev->ofdev.dev.of_node) {
|
if (pmz_ports[i].node == mdev->ofdev.dev.of_node)
|
||||||
struct uart_pmac_port *uap = &pmz_ports[i];
|
break;
|
||||||
|
if (i >= MAX_ZS_PORTS)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
uap->dev = mdev;
|
|
||||||
dev_set_drvdata(&mdev->ofdev.dev, uap);
|
uap = &pmz_ports[i];
|
||||||
if (macio_request_resources(uap->dev, "pmac_zilog"))
|
uap->dev = mdev;
|
||||||
printk(KERN_WARNING "%s: Failed to request resource"
|
uap->port.dev = &mdev->ofdev.dev;
|
||||||
", port still active\n",
|
dev_set_drvdata(&mdev->ofdev.dev, uap);
|
||||||
uap->node->name);
|
|
||||||
else
|
/* We still activate the port even when failing to request resources
|
||||||
uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED;
|
* to work around bugs in ancient Apple device-trees
|
||||||
return 0;
|
*/
|
||||||
}
|
if (macio_request_resources(uap->dev, "pmac_zilog"))
|
||||||
return -ENODEV;
|
printk(KERN_WARNING "%s: Failed to request resource"
|
||||||
|
", port still active\n",
|
||||||
|
uap->node->name);
|
||||||
|
else
|
||||||
|
uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED;
|
||||||
|
|
||||||
|
return uart_add_one_port(&pmz_uart_reg, &uap->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1637,12 +1586,15 @@ static int pmz_detach(struct macio_dev *mdev)
|
|||||||
if (!uap)
|
if (!uap)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
uart_remove_one_port(&pmz_uart_reg, &uap->port);
|
||||||
|
|
||||||
if (uap->flags & PMACZILOG_FLAG_RSRC_REQUESTED) {
|
if (uap->flags & PMACZILOG_FLAG_RSRC_REQUESTED) {
|
||||||
macio_release_resources(uap->dev);
|
macio_release_resources(uap->dev);
|
||||||
uap->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED;
|
uap->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED;
|
||||||
}
|
}
|
||||||
dev_set_drvdata(&mdev->ofdev.dev, NULL);
|
dev_set_drvdata(&mdev->ofdev.dev, NULL);
|
||||||
uap->dev = NULL;
|
uap->dev = NULL;
|
||||||
|
uap->port.dev = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1651,62 +1603,13 @@ static int pmz_detach(struct macio_dev *mdev)
|
|||||||
static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
|
static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
|
||||||
{
|
{
|
||||||
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
|
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
|
||||||
struct uart_state *state;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (uap == NULL) {
|
if (uap == NULL) {
|
||||||
printk("HRM... pmz_suspend with NULL uap\n");
|
printk("HRM... pmz_suspend with NULL uap\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
|
uart_suspend_port(&pmz_uart_reg, &uap->port);
|
||||||
return 0;
|
|
||||||
|
|
||||||
pmz_debug("suspend, switching to state %d\n", pm_state.event);
|
|
||||||
|
|
||||||
state = pmz_uart_reg.state + uap->port.line;
|
|
||||||
|
|
||||||
mutex_lock(&pmz_irq_mutex);
|
|
||||||
mutex_lock(&state->port.mutex);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&uap->port.lock, flags);
|
|
||||||
|
|
||||||
if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) {
|
|
||||||
/* Disable interrupt requests for the channel */
|
|
||||||
pmz_interrupt_control(uap, 0);
|
|
||||||
|
|
||||||
/* Disable receiver and transmitter */
|
|
||||||
uap->curregs[R3] &= ~RxENABLE;
|
|
||||||
uap->curregs[R5] &= ~TxENABLE;
|
|
||||||
|
|
||||||
/* Disable break assertion */
|
|
||||||
uap->curregs[R5] &= ~SND_BRK;
|
|
||||||
pmz_load_zsregs(uap, uap->curregs);
|
|
||||||
|
|
||||||
uap->flags |= PMACZILOG_FLAG_IS_ASLEEP;
|
|
||||||
mb();
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
|
|
||||||
if (ZS_IS_OPEN(uap) || ZS_IS_OPEN(uap->mate))
|
|
||||||
if (ZS_IS_ASLEEP(uap->mate) && ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
|
|
||||||
pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
|
|
||||||
disable_irq(uap->port.irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ZS_IS_CONS(uap))
|
|
||||||
uap->port.cons->flags &= ~CON_ENABLED;
|
|
||||||
|
|
||||||
/* Shut the chip down */
|
|
||||||
pmz_set_scc_power(uap, 0);
|
|
||||||
|
|
||||||
mutex_unlock(&state->port.mutex);
|
|
||||||
mutex_unlock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
pmz_debug("suspend, switching complete\n");
|
|
||||||
|
|
||||||
mdev->ofdev.dev.power.power_state = pm_state;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1715,74 +1618,20 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
|
|||||||
static int pmz_resume(struct macio_dev *mdev)
|
static int pmz_resume(struct macio_dev *mdev)
|
||||||
{
|
{
|
||||||
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
|
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
|
||||||
struct uart_state *state;
|
|
||||||
unsigned long flags;
|
|
||||||
int pwr_delay = 0;
|
|
||||||
|
|
||||||
if (uap == NULL)
|
if (uap == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
|
uart_resume_port(&pmz_uart_reg, &uap->port);
|
||||||
return 0;
|
|
||||||
|
|
||||||
pmz_debug("resume, switching to state 0\n");
|
|
||||||
|
|
||||||
state = pmz_uart_reg.state + uap->port.line;
|
|
||||||
|
|
||||||
mutex_lock(&pmz_irq_mutex);
|
|
||||||
mutex_lock(&state->port.mutex);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&uap->port.lock, flags);
|
|
||||||
if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
pwr_delay = __pmz_startup(uap);
|
|
||||||
|
|
||||||
/* Take care of config that may have changed while asleep */
|
|
||||||
__pmz_set_termios(&uap->port, &uap->termios_cache, NULL);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
|
|
||||||
if (ZS_IS_CONS(uap))
|
|
||||||
uap->port.cons->flags |= CON_ENABLED;
|
|
||||||
|
|
||||||
/* Re-enable IRQ on the controller */
|
|
||||||
if (ZS_IS_OPEN(uap) && !ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
|
|
||||||
pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
|
|
||||||
enable_irq(uap->port.irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ZS_IS_OPEN(uap)) {
|
|
||||||
spin_lock_irqsave(&uap->port.lock, flags);
|
|
||||||
pmz_interrupt_control(uap, 1);
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
bail:
|
|
||||||
mutex_unlock(&state->port.mutex);
|
|
||||||
mutex_unlock(&pmz_irq_mutex);
|
|
||||||
|
|
||||||
/* Right now, we deal with delay by blocking here, I'll be
|
|
||||||
* smarter later on
|
|
||||||
*/
|
|
||||||
if (pwr_delay != 0) {
|
|
||||||
pmz_debug("pmz: delaying %d ms\n", pwr_delay);
|
|
||||||
msleep(pwr_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
pmz_debug("resume, switching complete\n");
|
|
||||||
|
|
||||||
mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe all ports in the system and build the ports array, we register
|
* Probe all ports in the system and build the ports array, we register
|
||||||
* with the serial layer at this point, the macio-type probing is only
|
* with the serial layer later, so we get a proper struct device which
|
||||||
* used later to "attach" to the sysfs tree so we get power management
|
* allows the tty to attach properly. This is later than it used to be
|
||||||
* events
|
* but the tty layer really wants it that way.
|
||||||
*/
|
*/
|
||||||
static int __init pmz_probe(void)
|
static int __init pmz_probe(void)
|
||||||
{
|
{
|
||||||
@ -1818,8 +1667,10 @@ static int __init pmz_probe(void)
|
|||||||
/*
|
/*
|
||||||
* Fill basic fields in the port structures
|
* Fill basic fields in the port structures
|
||||||
*/
|
*/
|
||||||
pmz_ports[count].mate = &pmz_ports[count+1];
|
if (node_b != NULL) {
|
||||||
pmz_ports[count+1].mate = &pmz_ports[count];
|
pmz_ports[count].mate = &pmz_ports[count+1];
|
||||||
|
pmz_ports[count+1].mate = &pmz_ports[count];
|
||||||
|
}
|
||||||
pmz_ports[count].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
|
pmz_ports[count].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
|
||||||
pmz_ports[count].node = node_a;
|
pmz_ports[count].node = node_a;
|
||||||
pmz_ports[count+1].node = node_b;
|
pmz_ports[count+1].node = node_b;
|
||||||
@ -1857,8 +1708,8 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
|
|||||||
struct resource *r_ports;
|
struct resource *r_ports;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
|
r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
|
||||||
irq = platform_get_irq(uap->node, 0);
|
irq = platform_get_irq(uap->pdev, 0);
|
||||||
if (!r_ports || !irq)
|
if (!r_ports || !irq)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@ -1887,19 +1738,19 @@ static int __init pmz_probe(void)
|
|||||||
|
|
||||||
pmz_ports_count = 0;
|
pmz_ports_count = 0;
|
||||||
|
|
||||||
pmz_ports[0].mate = &pmz_ports[1];
|
|
||||||
pmz_ports[0].port.line = 0;
|
pmz_ports[0].port.line = 0;
|
||||||
pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
|
pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
|
||||||
pmz_ports[0].node = &scc_a_pdev;
|
pmz_ports[0].pdev = &scc_a_pdev;
|
||||||
err = pmz_init_port(&pmz_ports[0]);
|
err = pmz_init_port(&pmz_ports[0]);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
pmz_ports_count++;
|
pmz_ports_count++;
|
||||||
|
|
||||||
|
pmz_ports[0].mate = &pmz_ports[1];
|
||||||
pmz_ports[1].mate = &pmz_ports[0];
|
pmz_ports[1].mate = &pmz_ports[0];
|
||||||
pmz_ports[1].port.line = 1;
|
pmz_ports[1].port.line = 1;
|
||||||
pmz_ports[1].flags = 0;
|
pmz_ports[1].flags = 0;
|
||||||
pmz_ports[1].node = &scc_b_pdev;
|
pmz_ports[1].pdev = &scc_b_pdev;
|
||||||
err = pmz_init_port(&pmz_ports[1]);
|
err = pmz_init_port(&pmz_ports[1]);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -1915,16 +1766,35 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
|
|||||||
|
|
||||||
static int __init pmz_attach(struct platform_device *pdev)
|
static int __init pmz_attach(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct uart_pmac_port *uap;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Iterate the pmz_ports array to find a matching entry */
|
||||||
for (i = 0; i < pmz_ports_count; i++)
|
for (i = 0; i < pmz_ports_count; i++)
|
||||||
if (pmz_ports[i].node == pdev)
|
if (pmz_ports[i].pdev == pdev)
|
||||||
return 0;
|
break;
|
||||||
return -ENODEV;
|
if (i >= pmz_ports_count)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
uap = &pmz_ports[i];
|
||||||
|
uap->port.dev = &pdev->dev;
|
||||||
|
platform_set_drvdata(pdev, uap);
|
||||||
|
|
||||||
|
return uart_add_one_port(&pmz_uart_reg, &uap->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __exit pmz_detach(struct platform_device *pdev)
|
static int __exit pmz_detach(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct uart_pmac_port *uap = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (!uap)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
uart_remove_one_port(&pmz_uart_reg, &uap->port);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
uap->port.dev = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1956,38 +1826,13 @@ static struct console pmz_console = {
|
|||||||
*/
|
*/
|
||||||
static int __init pmz_register(void)
|
static int __init pmz_register(void)
|
||||||
{
|
{
|
||||||
int i, rc;
|
|
||||||
|
|
||||||
pmz_uart_reg.nr = pmz_ports_count;
|
pmz_uart_reg.nr = pmz_ports_count;
|
||||||
pmz_uart_reg.cons = PMACZILOG_CONSOLE;
|
pmz_uart_reg.cons = PMACZILOG_CONSOLE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register this driver with the serial core
|
* Register this driver with the serial core
|
||||||
*/
|
*/
|
||||||
rc = uart_register_driver(&pmz_uart_reg);
|
return uart_register_driver(&pmz_uart_reg);
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register each port with the serial core
|
|
||||||
*/
|
|
||||||
for (i = 0; i < pmz_ports_count; i++) {
|
|
||||||
struct uart_pmac_port *uport = &pmz_ports[i];
|
|
||||||
/* NULL node may happen on wallstreet */
|
|
||||||
if (uport->node != NULL)
|
|
||||||
rc = uart_add_one_port(&pmz_uart_reg, &uport->port);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err_out:
|
|
||||||
while (i-- > 0) {
|
|
||||||
struct uart_pmac_port *uport = &pmz_ports[i];
|
|
||||||
uart_remove_one_port(&pmz_uart_reg, &uport->port);
|
|
||||||
}
|
|
||||||
uart_unregister_driver(&pmz_uart_reg);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
#ifdef CONFIG_PPC_PMAC
|
||||||
@ -2086,10 +1931,13 @@ static void __exit exit_pmz(void)
|
|||||||
|
|
||||||
for (i = 0; i < pmz_ports_count; i++) {
|
for (i = 0; i < pmz_ports_count; i++) {
|
||||||
struct uart_pmac_port *uport = &pmz_ports[i];
|
struct uart_pmac_port *uport = &pmz_ports[i];
|
||||||
if (uport->node != NULL) {
|
#ifdef CONFIG_PPC_PMAC
|
||||||
uart_remove_one_port(&pmz_uart_reg, &uport->port);
|
if (uport->node != NULL)
|
||||||
pmz_dispose_port(uport);
|
pmz_dispose_port(uport);
|
||||||
}
|
#else
|
||||||
|
if (uport->pdev != NULL)
|
||||||
|
pmz_dispose_port(uport);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/* Unregister UART driver */
|
/* Unregister UART driver */
|
||||||
uart_unregister_driver(&pmz_uart_reg);
|
uart_unregister_driver(&pmz_uart_reg);
|
||||||
@ -2116,8 +1964,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
|
|||||||
struct uart_pmac_port *uap = &pmz_ports[con->index];
|
struct uart_pmac_port *uap = &pmz_ports[con->index];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (ZS_IS_ASLEEP(uap))
|
|
||||||
return;
|
|
||||||
spin_lock_irqsave(&uap->port.lock, flags);
|
spin_lock_irqsave(&uap->port.lock, flags);
|
||||||
|
|
||||||
/* Turn of interrupts and enable the transmitter. */
|
/* Turn of interrupts and enable the transmitter. */
|
||||||
@ -2162,8 +2008,13 @@ static int __init pmz_console_setup(struct console *co, char *options)
|
|||||||
if (co->index >= pmz_ports_count)
|
if (co->index >= pmz_ports_count)
|
||||||
co->index = 0;
|
co->index = 0;
|
||||||
uap = &pmz_ports[co->index];
|
uap = &pmz_ports[co->index];
|
||||||
|
#ifdef CONFIG_PPC_PMAC
|
||||||
if (uap->node == NULL)
|
if (uap->node == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
#else
|
||||||
|
if (uap->pdev == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
#endif
|
||||||
port = &uap->port;
|
port = &uap->port;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
#ifndef __PMAC_ZILOG_H__
|
#ifndef __PMAC_ZILOG_H__
|
||||||
#define __PMAC_ZILOG_H__
|
#define __PMAC_ZILOG_H__
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PMAC
|
|
||||||
#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
|
|
||||||
#define pmz_error(fmt, arg...) dev_err(&uap->dev->ofdev.dev, fmt, ## arg)
|
|
||||||
#define pmz_info(fmt, arg...) dev_info(&uap->dev->ofdev.dev, fmt, ## arg)
|
|
||||||
#else
|
|
||||||
#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
|
|
||||||
#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
|
|
||||||
#define pmz_info(fmt, arg...) dev_info(&uap->node->dev, fmt, ## arg)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At most 2 ESCCs with 2 ports each
|
* At most 2 ESCCs with 2 ports each
|
||||||
*/
|
*/
|
||||||
@ -35,7 +25,7 @@ struct uart_pmac_port {
|
|||||||
*/
|
*/
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
#else
|
#else
|
||||||
struct platform_device *node;
|
struct platform_device *pdev;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Port type as obtained from device tree (IRDA, modem, ...) */
|
/* Port type as obtained from device tree (IRDA, modem, ...) */
|
||||||
@ -50,14 +40,11 @@ struct uart_pmac_port {
|
|||||||
#define PMACZILOG_FLAG_REGS_HELD 0x00000010
|
#define PMACZILOG_FLAG_REGS_HELD 0x00000010
|
||||||
#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
|
#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
|
||||||
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
|
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
|
||||||
#define PMACZILOG_FLAG_ENABLED 0x00000080
|
|
||||||
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
||||||
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
||||||
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
|
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
|
||||||
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
||||||
#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000
|
|
||||||
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
||||||
#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
|
|
||||||
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
||||||
#define PMACZILOG_FLAG_BREAK 0x00010000
|
#define PMACZILOG_FLAG_BREAK 0x00010000
|
||||||
|
|
||||||
@ -74,6 +61,8 @@ struct uart_pmac_port {
|
|||||||
volatile struct dbdma_regs __iomem *rx_dma_regs;
|
volatile struct dbdma_regs __iomem *rx_dma_regs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned char irq_name[8];
|
||||||
|
|
||||||
struct ktermios termios_cache;
|
struct ktermios termios_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -388,9 +377,7 @@ static inline void zssync(struct uart_pmac_port *port)
|
|||||||
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
||||||
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
|
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
|
||||||
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
|
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
|
||||||
#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
|
|
||||||
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
|
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
|
||||||
#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
|
|
||||||
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
|
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
|
||||||
|
|
||||||
#endif /* __PMAC_ZILOG_H__ */
|
#endif /* __PMAC_ZILOG_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user