Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SUNSAB]: Fix several bugs.
This commit is contained in:
commit
91fe7d7cdd
|
@ -58,6 +58,7 @@ struct uart_sunsab_port {
|
||||||
unsigned char interrupt_mask1;/* ISR1 masking */
|
unsigned char interrupt_mask1;/* ISR1 masking */
|
||||||
unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
|
unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
|
||||||
unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
|
unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
|
||||||
|
unsigned int gis_shift;
|
||||||
int type; /* SAB82532 version */
|
int type; /* SAB82532 version */
|
||||||
|
|
||||||
/* Setting configuration bits while the transmitter is active
|
/* Setting configuration bits while the transmitter is active
|
||||||
|
@ -305,13 +306,15 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
|
||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
union sab82532_irq_status status;
|
union sab82532_irq_status status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned char gis;
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
|
||||||
status.stat = 0;
|
status.stat = 0;
|
||||||
if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA0)
|
gis = readb(&up->regs->r.gis) >> up->gis_shift;
|
||||||
|
if (gis & 1)
|
||||||
status.sreg.isr0 = readb(&up->regs->r.isr0);
|
status.sreg.isr0 = readb(&up->regs->r.isr0);
|
||||||
if (readb(&up->regs->r.gis) & SAB82532_GIS_ISA1)
|
if (gis & 2)
|
||||||
status.sreg.isr1 = readb(&up->regs->r.isr1);
|
status.sreg.isr1 = readb(&up->regs->r.isr1);
|
||||||
|
|
||||||
tty = NULL;
|
tty = NULL;
|
||||||
|
@ -327,35 +330,6 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id)
|
||||||
transmit_chars(up, &status);
|
transmit_chars(up, &status);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&up->port.lock);
|
|
||||||
|
|
||||||
if (tty)
|
|
||||||
tty_flip_buffer_push(tty);
|
|
||||||
|
|
||||||
up++;
|
|
||||||
|
|
||||||
spin_lock(&up->port.lock);
|
|
||||||
|
|
||||||
status.stat = 0;
|
|
||||||
if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB0)
|
|
||||||
status.sreg.isr0 = readb(&up->regs->r.isr0);
|
|
||||||
if (readb(&up->regs->r.gis) & SAB82532_GIS_ISB1)
|
|
||||||
status.sreg.isr1 = readb(&up->regs->r.isr1);
|
|
||||||
|
|
||||||
tty = NULL;
|
|
||||||
if (status.stat) {
|
|
||||||
if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
|
|
||||||
SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
|
|
||||||
(status.sreg.isr1 & SAB82532_ISR1_BRK))
|
|
||||||
|
|
||||||
tty = receive_chars(up, &status);
|
|
||||||
if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
|
|
||||||
(status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))
|
|
||||||
check_status(up, &status);
|
|
||||||
if (status.sreg.isr1 & (SAB82532_ISR1_ALLS | SAB82532_ISR1_XPR))
|
|
||||||
transmit_chars(up, &status);
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||||
|
|
||||||
if (tty)
|
if (tty)
|
||||||
|
@ -539,6 +513,10 @@ static int sunsab_startup(struct uart_port *port)
|
||||||
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
|
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
|
int err = request_irq(up->port.irq, sunsab_interrupt,
|
||||||
|
IRQF_SHARED, "sab", up);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
|
||||||
|
@ -641,6 +619,7 @@ static void sunsab_shutdown(struct uart_port *port)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||||
|
free_irq(up->port.irq, up);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1008,9 +987,11 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
|
||||||
if ((up->port.line & 0x1) == 0) {
|
if ((up->port.line & 0x1) == 0) {
|
||||||
up->pvr_dsr_bit = (1 << 0);
|
up->pvr_dsr_bit = (1 << 0);
|
||||||
up->pvr_dtr_bit = (1 << 1);
|
up->pvr_dtr_bit = (1 << 1);
|
||||||
|
up->gis_shift = 2;
|
||||||
} else {
|
} else {
|
||||||
up->pvr_dsr_bit = (1 << 3);
|
up->pvr_dsr_bit = (1 << 3);
|
||||||
up->pvr_dtr_bit = (1 << 2);
|
up->pvr_dtr_bit = (1 << 2);
|
||||||
|
up->gis_shift = 0;
|
||||||
}
|
}
|
||||||
up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
|
up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
|
||||||
writeb(up->cached_pvr, &up->regs->w.pvr);
|
writeb(up->cached_pvr, &up->regs->w.pvr);
|
||||||
|
@ -1023,19 +1004,6 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
|
||||||
up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
|
up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
|
||||||
up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
|
up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
|
||||||
|
|
||||||
if (!(up->port.line & 0x01)) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = request_irq(up->port.irq, sunsab_interrupt,
|
|
||||||
IRQF_SHARED, "sab", up);
|
|
||||||
if (err) {
|
|
||||||
of_iounmap(&op->resource[0],
|
|
||||||
up->port.membase,
|
|
||||||
sizeof(union sab82532_async_regs));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,52 +1019,60 @@ static int __devinit sab_probe(struct of_device *op, const struct of_device_id *
|
||||||
0,
|
0,
|
||||||
(inst * 2) + 0);
|
(inst * 2) + 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
|
|
||||||
err = sunsab_init_one(&up[1], op,
|
err = sunsab_init_one(&up[1], op,
|
||||||
sizeof(union sab82532_async_regs),
|
sizeof(union sab82532_async_regs),
|
||||||
(inst * 2) + 1);
|
(inst * 2) + 1);
|
||||||
if (err) {
|
if (err)
|
||||||
of_iounmap(&op->resource[0],
|
goto out1;
|
||||||
up[0].port.membase,
|
|
||||||
sizeof(union sab82532_async_regs));
|
|
||||||
free_irq(up[0].port.irq, &up[0]);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
||||||
&sunsab_reg, up[0].port.line);
|
&sunsab_reg, up[0].port.line);
|
||||||
uart_add_one_port(&sunsab_reg, &up[0].port);
|
|
||||||
|
|
||||||
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
sunserial_console_match(SUNSAB_CONSOLE(), op->node,
|
||||||
&sunsab_reg, up[1].port.line);
|
&sunsab_reg, up[1].port.line);
|
||||||
uart_add_one_port(&sunsab_reg, &up[1].port);
|
|
||||||
|
err = uart_add_one_port(&sunsab_reg, &up[0].port);
|
||||||
|
if (err)
|
||||||
|
goto out2;
|
||||||
|
|
||||||
|
err = uart_add_one_port(&sunsab_reg, &up[1].port);
|
||||||
|
if (err)
|
||||||
|
goto out3;
|
||||||
|
|
||||||
dev_set_drvdata(&op->dev, &up[0]);
|
dev_set_drvdata(&op->dev, &up[0]);
|
||||||
|
|
||||||
inst++;
|
inst++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
static void __devexit sab_remove_one(struct uart_sunsab_port *up)
|
out3:
|
||||||
{
|
uart_remove_one_port(&sunsab_reg, &up[0].port);
|
||||||
struct of_device *op = to_of_device(up->port.dev);
|
out2:
|
||||||
|
|
||||||
uart_remove_one_port(&sunsab_reg, &up->port);
|
|
||||||
if (!(up->port.line & 1))
|
|
||||||
free_irq(up->port.irq, up);
|
|
||||||
of_iounmap(&op->resource[0],
|
of_iounmap(&op->resource[0],
|
||||||
up->port.membase,
|
up[1].port.membase,
|
||||||
sizeof(union sab82532_async_regs));
|
sizeof(union sab82532_async_regs));
|
||||||
|
out1:
|
||||||
|
of_iounmap(&op->resource[0],
|
||||||
|
up[0].port.membase,
|
||||||
|
sizeof(union sab82532_async_regs));
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devexit sab_remove(struct of_device *op)
|
static int __devexit sab_remove(struct of_device *op)
|
||||||
{
|
{
|
||||||
struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
|
struct uart_sunsab_port *up = dev_get_drvdata(&op->dev);
|
||||||
|
|
||||||
sab_remove_one(&up[0]);
|
uart_remove_one_port(&sunsab_reg, &up[1].port);
|
||||||
sab_remove_one(&up[1]);
|
uart_remove_one_port(&sunsab_reg, &up[0].port);
|
||||||
|
of_iounmap(&op->resource[0],
|
||||||
|
up[1].port.membase,
|
||||||
|
sizeof(union sab82532_async_regs));
|
||||||
|
of_iounmap(&op->resource[0],
|
||||||
|
up[0].port.membase,
|
||||||
|
sizeof(union sab82532_async_regs));
|
||||||
|
|
||||||
dev_set_drvdata(&op->dev, NULL);
|
dev_set_drvdata(&op->dev, NULL);
|
||||||
|
|
||||||
|
@ -1143,6 +1119,7 @@ static int __init sunsab_init(void)
|
||||||
|
|
||||||
sunsab_reg.minor = sunserial_current_minor;
|
sunsab_reg.minor = sunserial_current_minor;
|
||||||
sunsab_reg.nr = num_channels;
|
sunsab_reg.nr = num_channels;
|
||||||
|
sunsab_reg.cons = SUNSAB_CONSOLE();
|
||||||
|
|
||||||
err = uart_register_driver(&sunsab_reg);
|
err = uart_register_driver(&sunsab_reg);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
Loading…
Reference in New Issue