#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
-static void handle_error(struct sci_port *port)
+static void handle_error(struct uart_port *port)
{ /* Clear error flags */
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
}
-static int get_char(struct sci_port *port)
+static int get_char(struct uart_port *port)
{
unsigned long flags;
unsigned short status;
#if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
#if defined(CONFIG_CPU_SH3)
-/* For SH7707, SH7709, SH7709A, SH7729 */
+/* For SH7707, SH7709, SH7709A, SH7729, SH7300*/
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
{
unsigned int fcr_val = 0;
-
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300) /* SH7300 doesn't use RTS/CTS */
{
unsigned short data;
/* Set /RTS2 (bit6) = 0 */
ctrl_outb(data&0xbf, SCPDR);
}
+#endif
sci_out(port, SCFCR, fcr_val);
}
#if !defined(SCI_ONLY)
if (port->type == PORT_SCIF) {
- txroom = 16 - (sci_in(port, SCFDR)>>8);
+ txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8);
} else {
txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
}
while (1) {
#if !defined(SCI_ONLY)
if (port->type == PORT_SCIF) {
- count = sci_in(port, SCFDR)&0x001f;
+ count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ;
} else {
count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
}
pr_debug("sci: BREAK detected\n");
}
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_ST40STB1) || \
- defined(CONFIG_CPU_SUBTYPE_SH7760)
+#if defined(SCIF_ORER)
/* XXX: Handle SCIF overrun error */
if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
sci_out(port, SCLSR, 0);
sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
}
} else {
+#if defined(SCIF_ORER)
+ if((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+ struct tty_struct *tty = port->info->tty;
+
+ sci_out(port, SCLSR, 0);
+ if(tty->flip.count<TTY_FLIPBUF_SIZE) {
+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ tty->flip.count++;
+ tty_flip_buffer_push(tty);
+ pr_debug("scif: overrun error\n");
+ }
+ }
+#endif
sci_rx_interrupt(irq, ptr, regs);
}
return IRQ_HANDLED;
}
+static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ unsigned short ssr_status, scr_status;
+ struct uart_port *port = ptr;
+
+ ssr_status = sci_in(port,SCxSR);
+ scr_status = sci_in(port,SCSCR);
+
+ /* Tx Interrupt */
+ if ((ssr_status&0x0020) && (scr_status&0x0080))
+ sci_tx_interrupt(irq, ptr, regs);
+ /* Rx Interrupt */
+ if ((ssr_status&0x0002) && (scr_status&0x0040))
+ sci_rx_interrupt(irq, ptr, regs);
+ /* Error Interrupt */
+ if ((ssr_status&0x0080) && (scr_status&0x0400))
+ sci_er_interrupt(irq, ptr, regs);
+ /* Break Interrupt */
+ if ((ssr_status&0x0010) && (scr_status&0x0200))
+ sci_br_interrupt(irq, ptr, regs);
+
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_CPU_FREQ
/*
* Here we define a transistion notifier so that we can update all of our
const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
"SCI Transmit Data Empty", "SCI Break" };
- for (i = 0; i < ARRAY_SIZE(handlers); i++) {
- if (!port->irqs[i])
- continue;
- if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT,
- desc[i], port)) {
+ if (port->irqs[0] == port->irqs[1]) {
+ if (!port->irqs[0]) {
+ printk(KERN_ERR "sci: Cannot allocate irq.(IRQ=0)\n");
+ return -ENODEV;
+ }
+ if (request_irq(port->irqs[0], sci_mpxed_interrupt, SA_INTERRUPT,
+ "sci", port)) {
printk(KERN_ERR "sci: Cannot allocate irq.\n");
return -ENODEV;
}
+ } else {
+ for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+ if (!port->irqs[i])
+ continue;
+ if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT,
+ desc[i], port)) {
+ printk(KERN_ERR "sci: Cannot allocate irq.\n");
+ return -ENODEV;
+ }
+ }
}
return 0;
{
int i;
- for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
- if (!port->irqs[i])
- continue;
-
- free_irq(port->irqs[i], port);
+ if (port->irqs[0] == port->irqs[1]) {
+ if (!port->irqs[0])
+ printk("sci: sci_free_irq error\n");
+ else
+ free_irq(port->irqs[0], port);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
+ if (!port->irqs[i])
+ continue;
+
+ free_irq(port->irqs[i], port);
+ }
}
}
/* Set RIE (Receive Interrupt Enable) bit in SCSCR */
local_irq_save(flags);
ctrl = sci_in(port, SCSCR);
- ctrl |= SCI_CTRL_FLAGS_RIE;
+ ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
sci_out(port, SCSCR, ctrl);
local_irq_restore(flags);
}
/* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
local_irq_save(flags);
ctrl = sci_in(port, SCSCR);
- ctrl &= ~SCI_CTRL_FLAGS_RIE;
+ ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
sci_out(port, SCSCR, ctrl);
local_irq_restore(flags);
}
case 38400: t = BPS_38400; break;
case 57600: t = BPS_57600; break;
case 115200: t = BPS_115200; break;
- default: t = BPS_115200; break;
+ default: t = SCBRR_VALUE(baud); break;
}
if (t > 0) {
struct sci_port *s = &sci_ports[port->line];
port->type = s->type;
+
+#if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+ if (port->mapbase == 0)
+ port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
+
+ port->membase = (void *)port->mapbase;
+#endif
}
static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
.irqs = SH3_IRDA_IRQS,
.init_pins = sci_init_pins_irda,
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
+ {
+ .port = {
+ .membase = (void *)0xA4430000,
+ .mapbase = 0xA4430000,
+ .iotype = SERIAL_IO_MEM,
+ .irq = 25,
+ .ops = &sci_uart_ops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH7300_SCIF0_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
+#elif defined(CONFIG_SH_RTS7751R2D)
+ {
+ .port = {
+ .membase = (void *)0xffe80000,
+ .mapbase = 0xffe80000,
+ .iotype = SERIAL_IO_MEM,
+ .irq = 43,
+ .ops = &sci_uart_ops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH4_SCIF_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
{
.port = {
.irqs = SH4_SCIF_IRQS,
.init_pins = sci_init_pins_scif,
},
+#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+ {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .irq = 42,
+ .ops = &sci_uart_ops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .type = PORT_SCIF,
+ .irqs = SH5_SCIF_IRQS,
+ .init_pins = sci_init_pins_scif,
+ },
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
{
.port = {
port = &serial_console_port->port;
port->type = serial_console_port->type;
+#ifdef CONFIG_SUPERH64
+ /* This is especially needed on sh64 to remap the SCIF */
+ sci_config_port(port, 0);
+#endif
+
/*
* We need to set the initial uartclk here, since otherwise it will
* only ever be setup at sci_init() time.
static int __init sci_console_init(void)
{
-#ifdef CONFIG_SH_EARLY_PRINTK
- extern void sh_console_unregister(void);
-
- /*
- * Now that the real console is available, unregister the one we
- * used while first booting.
- */
- sh_console_unregister();
-#endif
-
register_console(&serial_console);
-
return 0;
}
static int __init kgdb_console_init(void)
{
register_console(&kgdb_console);
-
return 0;
}