void handle_error(void) { sci_in(&sh_sci, SCxSR); sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); sci_in(&sh_sci, SCLSR); sci_out(&sh_sci, SCLSR, 0x00); }
static void sci_setsignals(struct sci_port *port, int dtr, int rts) { /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */ /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */ /* If you have signals for DTR and DCD, please implement here. */ #if defined(CONFIG_SH_SECUREEDGE5410) int flags; save_and_cli(flags); if (port == &sci_ports[1]) { /* port 1 only */ if (dtr == 0) SECUREEDGE_WRITE_IOPORT(0x0080, 0x0080); else if (dtr == 1) SECUREEDGE_WRITE_IOPORT(0x0000, 0x0080); if ((sci_in(port, SCFCR) & SCFCR_MCE) == 0) { if (rts) sci_out(port, SCSPTR, sci_in(port, SCSPTR) & ~0x40); else sci_out(port, SCSPTR, sci_in(port, SCSPTR) | 0x40); } } if (port == &sci_ports[0]) { /* port 0 only */ if (dtr == 0) SECUREEDGE_WRITE_IOPORT(0x0200, 0x0200); else if (dtr == 1) SECUREEDGE_WRITE_IOPORT(0x0000, 0x0200); if (rts == 0) SECUREEDGE_WRITE_IOPORT(0x0100, 0x0100); else if (rts == 1) SECUREEDGE_WRITE_IOPORT(0x0000, 0x0100); } restore_flags(flags); #endif }
static irqreturn_t sci_er_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; /* Handle errors */ if (port->type == PORT_SCI) { if (sci_handle_errors(port)) { /* discard character in rx buffer */ sci_in(port, SCxSR); 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->port.tty; sci_out(port, SCLSR, 0); tty_insert_flip_char(tty, 0, TTY_OVERRUN); tty_flip_buffer_push(tty); pr_debug("scif: overrun error\n"); } #endif sci_rx_interrupt(irq, ptr); } sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); /* Kick the transmission */ sci_tx_interrupt(irq, ptr); return IRQ_HANDLED; }
static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; unsigned long flags; int t; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); switch (baud) { case 0: t = -1; break; default: { #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) struct clk *clk = clk_get(NULL, "module_clk"); t = SCBRR_VALUE(baud, clk_get_rate(clk)); clk_put(clk); #else t = SCBRR_VALUE(baud); #endif } break; } spin_lock_irqsave(&port->lock, flags); do { status = sci_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ #if !defined(SCI_ONLY) if (port->type == PORT_SCIF) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); #endif smr_val = sci_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; if (termios->c_cflag & PARENB) smr_val |= 0x20; if (termios->c_cflag & PARODD) smr_val |= 0x30; if (termios->c_cflag & CSTOPB) smr_val |= 0x08; uart_update_timeout(port, termios->c_cflag, baud); sci_out(port, SCSMR, smr_val); if (t > 0) { if(t >= 256) { sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); t >>= 2; } else {
/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ static void change_speed(struct sci_struct *sci) { unsigned cflag; unsigned int status; unsigned int smr_val; unsigned int ddr; unsigned int i,t; if (!sci->info->tty || !sci->info->tty->termios) return; cflag = sci->info->tty->termios->c_cflag; do status = sci_in(sci, SCI_SSR); while (!(status & SCI_SSR_TEND)); sci_out(sci, SCI_SCR, 0x00); /* TE=0, RE=0, CKE1=0 */ smr_val = sci_in(sci, SCI_SMR) & 3; if ((cflag & CSIZE) == CS7) smr_val |= 0x40; if (cflag & PARENB) smr_val |= 0x20; if (cflag & PARODD) smr_val |= 0x10; if (cflag & CSTOPB) smr_val |= 0x08; t=0; cflag = sci->info->tty->termios->c_cflag; i = cflag & CBAUD; if (i & CBAUDEX) { i &= ~CBAUDEX; if (i < 1 || i > 2) sci->info->tty->termios->c_cflag &= ~CBAUDEX; else i += 15; } if (i == 15) { if ((sci->info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) i += 1; if ((sci->info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) i += 2; if ((sci->info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) t = sci->info->custom_divisor; } if (t==0) t=sci_baud_table[i]; if (t > 0) { if(t >= 256) { smr_val = (t >> 8) & 3; } sci_out(sci, SCI_BRR, t & 0xff); udelay(32*(1 << (t*2))*(t & 0xff)*CONFIG_CLK_FREQ); /* Wait one bit interval */ }
/* For SH7750 */ static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag) { unsigned int fcr_val = 0; if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } else { sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */ } sci_out(port, SCFCR, fcr_val); }
void serial_raw_putc(const char c) { while (1) { /* Tx fifo is empty */ if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) break; } sci_out(&sh_sci, SCxTDR, c); sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); }
/* Write a char */ static void kgdb_put_char(struct sci_port *port, char c) { unsigned short status; do status = sci_in(port, SCxSR); while (!(status & SCxSR_TDxE(port))); sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); }
static void scif_sercon_putc(int c) { while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE)) ; sci_in(&scif_port, SCxSR); sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40)); sci_out(&scif_port, SCxTDR, c); while ((sci_in(&scif_port, SCxSR) & 0x40) == 0) ; if (c == '\n') scif_sercon_putc('\r'); }
/* 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; /* We need to set SCPCR to enable RTS/CTS */ data = ctrl_inw(SCPCR); /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ ctrl_outw(data&0x0fcf, SCPCR); } if (cflag & CRTSCTS) fcr_val |= SCFCR_MCE; else { unsigned short data; /* We need to set SCPCR to enable RTS/CTS */ data = ctrl_inw(SCPCR); /* Clear out SCP7MD1,0, SCP4MD1,0, Set SCP6MD1,0 = {01} (output) */ ctrl_outw((data&0x0fcf)|0x1000, SCPCR); data = ctrl_inb(SCPDR); /* Set /RTS2 (bit6) = 0 */ ctrl_outb(data&0xbf, SCPDR); } #endif sci_out(port, SCFCR, fcr_val); }
static void sci_transmit_chars(struct uart_port *port) { struct circ_buf *xmit = &port->info->xmit; unsigned int stopped = uart_tx_stopped(port); unsigned long flags; unsigned short status; unsigned short ctrl; int count, txroom; status = sci_in(port, SCxSR); if (!(status & SCxSR_TDxE(port))) { local_irq_save(flags); ctrl = sci_in(port, SCSCR); if (uart_circ_empty(xmit)) { ctrl &= ~SCI_CTRL_FLAGS_TIE; } else { ctrl |= SCI_CTRL_FLAGS_TIE; } sci_out(port, SCSCR, ctrl); local_irq_restore(flags); return; } #if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8); } else {
/* For SH7707, SH7709, SH7709A, SH7729 */ static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag) { unsigned int fcr_val = 0; { unsigned short data; /* We need to set SCPCR to enable RTS/CTS */ data = ctrl_inw(SCPCR); /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ ctrl_outw(data&0x0fcf, SCPCR); } if (cflag & CRTSCTS) fcr_val |= SCFCR_MCE; else { unsigned short data; /* We need to set SCPCR to enable RTS/CTS */ data = ctrl_inw(SCPCR); /* Clear out SCP7MD1,0, SCP4MD1,0, Set SCP6MD1,0 = {01} (output) */ ctrl_outw((data&0x0fcf)|0x1000, SCPCR); data = ctrl_inb(SCPDR); /* Set /RTS2 (bit6) = 0 */ ctrl_outb(data&0xbf, SCPDR); } sci_out(port, SCFCR, fcr_val); }
static inline int sci_handle_breaks(struct uart_port *port) { int copied = 0; unsigned short status = sci_in(port, SCxSR); struct tty_struct *tty = port->info->tty; struct sci_port *s = &sci_ports[port->line]; if (!s->break_flag && status & SCxSR_BRK(port)) { #if defined(CONFIG_CPU_SH3) /* Debounce break */ s->break_flag = 1; #endif /* Notify of BREAK */ if (tty_insert_flip_char(tty, 0, TTY_BREAK)) copied++; pr_debug("sci: BREAK detected\n"); } #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); if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { copied++; pr_debug("sci: overrun error\n"); } } #endif if (copied) tty_flip_buffer_push(tty); return copied; }
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) { unsigned int fcr_val = 0; unsigned short data; if (cflag & CRTSCTS) { /* enable RTS/CTS */ if (port->mapbase == 0xa4430000) { /* SCIF0 */ /* Clear PTCR bit 9-2; enable all scif pins but sck */ data = ctrl_inw(PORT_PTCR); ctrl_outw((data & 0xfc03), PORT_PTCR); } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ /* Clear PVCR bit 9-2 */ data = ctrl_inw(PORT_PVCR); ctrl_outw((data & 0xfc03), PORT_PVCR); } fcr_val |= SCFCR_MCE; } else { if (port->mapbase == 0xa4430000) { /* SCIF0 */ /* Clear PTCR bit 5-2; enable only tx and rx */ data = ctrl_inw(PORT_PTCR); ctrl_outw((data & 0xffc3), PORT_PTCR); } else if (port->mapbase == 0xa4438000) { /* SCIF1 */ /* Clear PVCR bit 5-2 */ data = ctrl_inw(PORT_PVCR); ctrl_outw((data & 0xffc3), PORT_PVCR); } } sci_out(port, SCFCR, fcr_val); }
static void put_char(struct uart_port *port, char c) { unsigned long flags; unsigned short status; spin_lock_irqsave(&port->lock, flags); do { status = sci_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); spin_unlock_irqrestore(&port->lock, flags); }
static void put_char(struct sci_port *port, char c) { unsigned long flags; unsigned short status; save_and_cli(flags); do status = sci_in(port, SCxSR); while (!(status & SCxSR_TDxE(port))); sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); restore_flags(flags); }
static void sci_stop_tx(struct uart_port *port) { unsigned short ctrl; /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); ctrl &= ~SCI_CTRL_FLAGS_TIE; sci_out(port, SCSCR, ctrl); }
static void sci_init_pins_irda(struct sci_port* port, unsigned int cflag) { unsigned int fcr_val = 0; if (cflag & CRTSCTS) fcr_val |= SCFCR_MCE; sci_out(port, SCFCR, fcr_val); }
static void sci_stop_rx(struct uart_port *port) { unsigned short ctrl; /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); sci_out(port, SCSCR, ctrl); }
static void sci_start_rx(struct uart_port *port, unsigned int tty_start) { unsigned short ctrl; /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE; sci_out(port, SCSCR, ctrl); }
static irqreturn_t sci_br_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; /* Handle BREAKs */ sci_handle_breaks(port); sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); return IRQ_HANDLED; }
static void sci_init_pins_scif(struct uart_port* port, unsigned int cflag) { unsigned int fcr_val = 0; set_sh771x_scif_pfc(port); if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } sci_out(port, SCFCR, fcr_val); }
static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; int t = -1; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); if (likely(baud)) t = SCBRR_VALUE(baud, port->uartclk); do { status = sci_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ #if !defined(SCI_ONLY) if (port->type == PORT_SCIF) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); #endif smr_val = sci_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) smr_val |= 0x40; if (termios->c_cflag & PARENB) smr_val |= 0x20; if (termios->c_cflag & PARODD) smr_val |= 0x30; if (termios->c_cflag & CSTOPB) smr_val |= 0x08; uart_update_timeout(port, termios->c_cflag, baud); sci_out(port, SCSMR, smr_val); if (t > 0) { if(t >= 256) { sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); t >>= 2; } else {
static int get_char(struct uart_port *port) { unsigned long flags; unsigned short status; int c; spin_lock_irqsave(&port->lock, flags); do { status = sci_in(port, SCxSR); if (status & SCxSR_ERRORS(port)) { /* Clear error flags. */ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); continue; } } while (!(status & SCxSR_RDxF(port))); c = sci_in(port, SCxRDR); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); spin_unlock_irqrestore(&port->lock, flags); return c; }
/* * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 * devices that aren't using sh-ipl+g. */ static void scif_sercon_init(char *s) { struct uart_port *port = &scif_port; unsigned baud = DEFAULT_BAUD; unsigned int status; char *e; if (*s == ',') ++s; if (*s) { /* ignore ioport/device name */ s += strcspn(s, ","); if (*s == ',') s++; } if (*s) { baud = simple_strtoul(s, &e, 0); if (baud == 0 || s == e) baud = DEFAULT_BAUD; } do { status = sci_in(port, SCxSR); } while (!(status & SCxSR_TEND(port))); sci_out(port, SCSCR, 0); /* TE=0, RE=0 */ sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); sci_out(port, SCSMR, 0); /* Set baud rate */ sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) / (32 * baud) - 1); udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */ sci_out(port, SCSPTR, 0); sci_out(port, SCxSR, 0x60); sci_out(port, SCLSR, 0); sci_out(port, SCFCR, 0); sci_out(port, SCSCR, 0x30); /* TE=1, RE=1 */ }
/* Breakpoint if there's a break sent on the serial port */ static void kgdb_break_interrupt(int irq, void *ptr, struct pt_regs *regs) { struct sci_port *port = ptr; unsigned short status = sci_in(port, SCxSR); if (status & SCxSR_BRK(port)) { /* Break into the debugger if a break is detected */ BREAKPOINT(); /* Clear */ sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); } }
/* Get a char if there is one, else ret -1 */ static int kgdb_get_char(struct sci_port *port) { int c; if (kgdb_is_char_ready(port) == 0) c = -1; else { c = sci_in(port, SCxRDR); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port)); } return c; }
static void scif_sercon_init(char *s) { sci_out(&scif_port, SCSCR, 0x0000); /* clear TE and RE */ sci_out(&scif_port, SCFCR, 0x4006); /* reset */ sci_out(&scif_port, SCSCR, 0x0000); /* select internal clock */ sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE); sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE); mdelay(1); /* wait 1-bit time */ sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */ sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */ }
static irqreturn_t sci_br_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; /* Handle BREAKs */ sci_handle_breaks(port); #ifdef CONFIG_SH_KGDB /* Break into the debugger if a break is detected */ BREAKPOINT(); #endif sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port)); return IRQ_HANDLED; }
/* For SH7750 */ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) { unsigned int fcr_val = 0; if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } else { #ifdef CONFIG_CPU_SUBTYPE_SH7343 /* Nothing */ #elif defined(CONFIG_CPU_SUBTYPE_SH7780) ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ #else ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ #endif } sci_out(port, SCFCR, fcr_val); }