From ba7107616869bff7dc80627eab666fceb5ff4fb5 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 12 Oct 2001 13:19:08 +0000 Subject: 2001-10-11 Alexandra Kossovsky * clock/Makefile.am, clock/ckinit.c, clock/.cvsignore, Makefile.am, include/Makefile.am, include/iosh7750.h, include/ipl.h, include/ispsh7750.h, include/sh4_regs.h, include/sh4uart.h, include/sh7750_regs.h, include/.cvsignore, sci/Makefile.am, sci/console.c, sci/sh4uart.c, sci/.cvsignore, score/Makefile.am, score/cpu_asm.c, score/ispsh7750.c, score/.cvsignore, timer/Makefile.am, timer/timer.c, timer/.cvsignore, configure.ac, .cvsignore, ChangeLog: New files. Reviewed and updated to latest automake and autoconf standards by Ralf Corsepius . --- c/src/lib/libcpu/sh/sh7750/sci/.cvsignore | 2 + c/src/lib/libcpu/sh/sh7750/sci/Makefile.am | 29 + c/src/lib/libcpu/sh/sh7750/sci/console.c | 484 +++++++++++++++ c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c | 945 +++++++++++++++++++++++++++++ 4 files changed, 1460 insertions(+) create mode 100644 c/src/lib/libcpu/sh/sh7750/sci/.cvsignore create mode 100644 c/src/lib/libcpu/sh/sh7750/sci/Makefile.am create mode 100644 c/src/lib/libcpu/sh/sh7750/sci/console.c create mode 100644 c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c (limited to 'c/src/lib/libcpu/sh/sh7750/sci') diff --git a/c/src/lib/libcpu/sh/sh7750/sci/.cvsignore b/c/src/lib/libcpu/sh/sh7750/sci/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7750/sci/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libcpu/sh/sh7750/sci/Makefile.am b/c/src/lib/libcpu/sh/sh7750/sci/Makefile.am new file mode 100644 index 0000000000..e37a7e7984 --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7750/sci/Makefile.am @@ -0,0 +1,29 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/sci.rel + +C_FILES = console.c sh4uart.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(top_srcdir)/../../../../../../make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +all-local: $(ARCH) $(OBJS) $(PGM) + +.PRECIOUS: $(PGM) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libcpu/sh/sh7750/sci/console.c b/c/src/lib/libcpu/sh/sh7750/sci/console.c new file mode 100644 index 0000000000..46d5f2eefc --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7750/sci/console.c @@ -0,0 +1,484 @@ +/* + * Console driver for SH-4 UART modules + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia + * Author: Alexandra Kossovsky + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include "sh/sh4uart.h" + +/* Descriptor structures for two on-chip UART channels */ +sh4uart sh4_uarts[2]; + +/* Console operations mode: + * 0 - raw (non-termios) polled input/output + * 1 - termios-based polled input/output + * 2 - termios-based interrupt-driven input/output + * 3 - non-termios over gdb stub + */ +int console_mode = 3; +#define CONSOLE_MODE_RAW (0) +#define CONSOLE_MODE_POLL (1) +#define CONSOLE_MODE_INT (2) +#define CONSOLE_MODE_IPL (3) + +/* Wrapper functions for SH-4 UART generic driver */ + +/* console_poll_read -- + * wrapper for poll read function + * + * PARAMETERS: + * minor - minor device number + * + * RETURNS: + * character code readed from UART, or -1 if there is no characters + * available + */ +static int +console_poll_read(int minor) +{ + return sh4uart_poll_read(&sh4_uarts[minor]); +} + +/* console_interrupt_write -- + * wrapper for interrupt write function + * + * PARAMETERS: + * minor - minor device number + * buf - output buffer + * len - output buffer length + * + * RETURNS: + * result code + */ +static int +console_interrupt_write(int minor, const char *buf, int len) +{ + return sh4uart_interrupt_write(&sh4_uarts[minor], buf, len); +} + +/* console_poll_write -- + * wrapper for polling mode write function + * + * PARAMETERS: + * minor - minor device number + * buf - output buffer + * len - output buffer length + * + * RETURNS: + * result code + */ +static int +console_poll_write(int minor, const char *buf, int len) +{ + return sh4uart_poll_write(&sh4_uarts[minor], buf, len); +} + +/* console_set_attributes -- + * wrapper for hardware-dependent termios attributes setting + * + * PARAMETERS: + * minor - minor device number + * t - pointer to the termios structure + * + * RETURNS: + * result code + */ +static int +console_set_attributes(int minor, const struct termios *t) +{ + return sh4uart_set_attributes(&sh4_uarts[minor], t); +} + +/* console_stop_remote_tx -- + * wrapper for stopping data flow from remote party. + * + * PARAMETERS: + * minor - minor device number + * + * RETURNS: + * result code + */ +static int +console_stop_remote_tx(int minor) +{ + if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0])) + return sh4uart_stop_remote_tx(&sh4_uarts[minor]); + else + return RTEMS_INVALID_NUMBER; +} + +/* console_start_remote_tx -- + * wrapper for resuming data flow from remote party. + * + * PARAMETERS: + * minor - minor device number + * + */ +static int +console_start_remote_tx(int minor) +{ + if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0])) + return sh4uart_start_remote_tx(&sh4_uarts[minor]); + else + return RTEMS_INVALID_NUMBER; +} + +/* console_first_open -- + * wrapper for UART controller initialization functions + * + * PARAMETERS: + * major - major device number + * minor - minor device number + * arg - libio device open argument + * + * RETURNS: + * error code + */ +static int +console_first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *args = arg; + rtems_status_code sc; + + sc = sh4uart_init(&sh4_uarts[minor], /* uart */ + args->iop->data1, /* tty */ + minor+1, /* channel */ + (console_mode == CONSOLE_MODE_INT)); + + if (sc == RTEMS_SUCCESSFUL) + sc = sh4uart_reset(&sh4_uarts[minor]); + + return sc; +} + +/* console_last_close -- + * wrapper for UART controller close function + * + * PARAMETERS: + * major - major device number + * minor - minor device number + * arg - libio device close argument + * + * RETURNS: + * error code + */ +static int +console_last_close(int major, int minor, void *arg) +{ + return sh4uart_disable(&sh4_uarts[minor]); +} + +/* console_reserve_resources -- + * reserve termios resources for 2 UART channels + * + * PARAMETERS: + * configuration -- pointer to the RTEMS configuration table + * + * RETURNS: + * none + */ +void +console_reserve_resources(rtems_configuration_table *configuration) +{ + if ((console_mode != CONSOLE_MODE_RAW) && + (console_mode != CONSOLE_MODE_IPL)) + rtems_termios_reserve_resources (configuration, 2); +} + +/* console_initialize -- + * This routine initializes the console IO drivers and register devices + * in RTEMS I/O system. + * + * PARAMETERS: + * major - major console device number + * minor - minor console device number (not used) + * arg - device initialize argument + * + * RETURNS: + * RTEMS error code (RTEMS_SUCCESSFUL if device initialized successfuly) + */ +rtems_device_driver +console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + +#ifdef SH4_WITH_IPL + /* booting from flash we cannot have IPL console */ + if (boot_mode != SH4_BOOT_MODE_IPL && console_mode == CONSOLE_MODE_IPL) + console_mode = CONSOLE_MODE_INT; + + /* break out from gdb if neccessary */ + if (boot_mode == SH4_BOOT_MODE_IPL && console_mode != CONSOLE_MODE_IPL) + ipl_finish(); +#endif + + /* + * Set up TERMIOS + */ + if ((console_mode != CONSOLE_MODE_RAW) && + (console_mode != CONSOLE_MODE_IPL)) + rtems_termios_initialize (); + + /* + * Register the devices + */ + status = rtems_io_register_name ("/dev/console", major, 0); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + status = rtems_io_register_name ("/dev/aux", major, 1); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + if (console_mode == CONSOLE_MODE_RAW) + { + rtems_status_code sc; + sc = sh4uart_init(&sh4_uarts[0], /* uart */ + NULL, /* tty */ + 1, /* UART channel number */ + 0); /* Poll-mode */ + + if (sc == RTEMS_SUCCESSFUL) + sc = sh4uart_reset(&sh4_uarts[0]); + + sc = sh4uart_init(&sh4_uarts[1], /* uart */ + NULL, /* tty */ + 2, /* UART channel number */ + 0); /* Poll-mode */ + + if (sc == RTEMS_SUCCESSFUL) + sc = sh4uart_reset(&sh4_uarts[1]); + + return sc; + } + + return RTEMS_SUCCESSFUL; +} + +/* console_open -- + * Open console device driver. Pass appropriate termios callback + * functions to termios library. + * + * PARAMETERS: + * major - major device number for console devices + * minor - minor device number for console + * arg - device opening argument + * + * RETURNS: + * RTEMS error code + */ +rtems_device_driver +console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + static const rtems_termios_callbacks intr_callbacks = { + console_first_open, /* firstOpen */ + console_last_close, /* lastClose */ + NULL, /* pollRead */ + console_interrupt_write, /* write */ + console_set_attributes, /* setAttributes */ + console_stop_remote_tx, /* stopRemoteTx */ + console_start_remote_tx, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; + static const rtems_termios_callbacks poll_callbacks = { + console_first_open, /* firstOpen */ + console_last_close, /* lastClose */ + console_poll_read, /* pollRead */ + console_poll_write, /* write */ + console_set_attributes, /* setAttributes */ + console_stop_remote_tx, /* stopRemoteTx */ + console_start_remote_tx, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ + }; + + switch (console_mode) + { + case CONSOLE_MODE_RAW: + case CONSOLE_MODE_IPL: + return RTEMS_SUCCESSFUL; + + case CONSOLE_MODE_INT: + return rtems_termios_open(major, minor, arg, &intr_callbacks); + + case CONSOLE_MODE_POLL: + return rtems_termios_open(major, minor, arg, &poll_callbacks); + + default: + rtems_fatal_error_occurred(0xC07A1310); + } + + return RTEMS_INTERNAL_ERROR; +} + +/* console_close -- + * Close console device. + * + * PARAMETERS: + * major - major device number for console devices + * minor - minor device number for console + * arg - device close argument + * + * RETURNS: + * RTEMS error code + */ +rtems_device_driver +console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + if ((console_mode != CONSOLE_MODE_RAW) && + (console_mode != CONSOLE_MODE_IPL)) + return rtems_termios_close (arg); + else + return RTEMS_SUCCESSFUL; +} + +/* console_read -- + * Read from the console device + * + * PARAMETERS: + * major - major device number for console devices + * minor - minor device number for console + * arg - device read argument + * + * RETURNS: + * RTEMS error code + */ +rtems_device_driver +console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + if ((console_mode != CONSOLE_MODE_RAW) && + (console_mode != CONSOLE_MODE_IPL)) + { + return rtems_termios_read (arg); + } + else + { + rtems_libio_rw_args_t *argp = arg; + char *buf = argp->buffer; + int count = argp->count; + int n = 0; + int c; + while (n < count) + { + do { + c = (console_mode == CONSOLE_MODE_RAW) ? + sh4uart_poll_read(&sh4_uarts[minor]) : + ipl_console_poll_read(minor); + } while (c == -1); + if (c == '\r') + c = '\n'; + *(buf++) = c; + n++; + if (c == '\n') + break; + } + argp->bytes_moved = n; + return RTEMS_SUCCESSFUL; + } +} + +/* console_write -- + * Write to the console device + * + * PARAMETERS: + * major - major device number for console devices + * minor - minor device number for console + * arg - device write argument + * + * RETURNS: + * RTEMS error code + */ +rtems_device_driver +console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + switch (console_mode) + { + case CONSOLE_MODE_POLL: + case CONSOLE_MODE_INT: + return rtems_termios_write (arg); + case CONSOLE_MODE_RAW: + { + rtems_libio_rw_args_t *argp = arg; + char cr = '\r'; + char *buf = argp->buffer; + int count = argp->count; + int i; + + for (i = 0; i < count; i++) + { + if (*buf == '\n') + sh4uart_poll_write(&sh4_uarts[minor], &cr, 1); + sh4uart_poll_write(&sh4_uarts[minor], buf, 1); + buf++; + } + argp->bytes_moved = count; + return RTEMS_SUCCESSFUL; + } +#ifdef SH4_WITH_IPL + case CONSOLE_MODE_IPL: + { + rtems_libio_rw_args_t *argp = arg; + char *buf = argp->buffer; + int count = argp->count; + ipl_console_poll_write(minor, buf, count); + argp->bytes_moved = count; + return RTEMS_SUCCESSFUL; + } +#endif + default: /* Unreachable */ + return RTEMS_NOT_DEFINED; + } +} + +/* console_control -- + * Handle console device I/O control (IOCTL) + * + * PARAMETERS: + * major - major device number for console devices + * minor - minor device number for console + * arg - device ioctl argument + * + * RETURNS: + * RTEMS error code + */ +rtems_device_driver +console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + if ((console_mode != CONSOLE_MODE_RAW) && + (console_mode != CONSOLE_MODE_IPL)) + { + return rtems_termios_ioctl (arg); + } + else + { + return RTEMS_SUCCESSFUL; + } +} + + + diff --git a/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c b/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c new file mode 100644 index 0000000000..7d6c83525b --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c @@ -0,0 +1,945 @@ +/* + * Generic UART Serial driver for SH-4 processors + * + * This driver uses variable SH4_CPU_HZ_Frequency, + * which should be defined in bsp to HZ macro. + * + * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed. + * Author: Alexandra Kossovsky + * + * COPYRIGHT (c) 1989-2000. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + * + */ + +#include +#include +#include +#include "sh/sh4uart.h" + +#ifndef SH4_UART_INTERRUPT_LEVEL +#define SH4_UART_INTERRUPT_LEVEL 4 +#endif + +/* Forward function declarations */ +static rtems_isr +sh4uart1_interrupt_transmit(rtems_vector_number vec); +static rtems_isr +sh4uart1_interrupt_receive(rtems_vector_number vec); +static rtems_isr +sh4uart2_interrupt_transmit(rtems_vector_number vec); +static rtems_isr +sh4uart2_interrupt_receive(rtems_vector_number vec); + +/* + * sh4uart_init -- + * This function verifies the input parameters and perform initialization + * of the SH-4 on-chip UART descriptor structure. + * + * PARAMETERS: + * uart - pointer to the UART channel descriptor structure + * tty - pointer to termios structure + * chn - channel number (SH4_SCI/SH4_SCIF -- 1/2) + * int_driven - interrupt-driven (1) or polled (0) I/O mode + * + * RETURNS: + * RTEMS_SUCCESSFUL if all parameters are valid, or error code + */ +rtems_status_code +sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven) +{ + if (uart == NULL) + return RTEMS_INVALID_ADDRESS; + + if ((chn != SH4_SCI) && (chn != SH4_SCIF)) + return RTEMS_INVALID_NUMBER; + + uart->chn = chn; + uart->tty = tty; + uart->int_driven = int_driven; + +#if 0 + sh4uart_poll_write(uart, "init", 4); +#endif + return RTEMS_SUCCESSFUL; +} + +/* + * sh4uart_get_Pph -- + * Get current peripheral module clock. + * + * PARAMETERS: none; + * Cpu clock is get from SH4_CPU_HZ_Frequency. + * This variable should be defined in bsp. + * + * RETURNS: + * peripheral module clock in Hz. + */ +rtems_unsigned32 +sh4uart_get_Pph(void) +{ + rtems_unsigned16 frqcr = *(volatile rtems_unsigned16 *)SH7750_FRQCR; + rtems_unsigned32 Pph = SH4_CPU_HZ_Frequency; + + switch (frqcr & SH7750_FRQCR_IFC) + { + case SH7750_FRQCR_IFCDIV1: + break; + + case SH7750_FRQCR_IFCDIV2: + Pph *= 2; + break; + + case SH7750_FRQCR_IFCDIV3: + Pph *= 3; + break; + + case SH7750_FRQCR_IFCDIV4: + Pph *= 4; + break; + + case SH7750_FRQCR_IFCDIV6: + Pph *= 6; + break; + + case SH7750_FRQCR_IFCDIV8: + Pph *= 8; + break; + + default: /* unreachable */ + break; + } + + switch (frqcr & SH7750_FRQCR_PFC) + { + case SH7750_FRQCR_PFCDIV2: + Pph /= 2; + break; + + case SH7750_FRQCR_PFCDIV3: + Pph /= 3; + break; + + case SH7750_FRQCR_PFCDIV4: + Pph /= 4; + break; + + case SH7750_FRQCR_PFCDIV6: + Pph /= 6; + break; + + case SH7750_FRQCR_PFCDIV8: + Pph /= 8; + break; + + default: /* unreachable */ + break; + } + + return Pph; +} + +/* + * sh4uart_set_baudrate -- + * Program the UART timer to specified baudrate + * + * PARAMETERS: + * uart - pointer to UART descriptor structure + * baud - termios baud rate (B50, B9600, etc...) + * + * ALGORITHM: + * see SH7750 Hardware Manual. + * + * RETURNS: + * none + */ +static void +sh4uart_set_baudrate(sh4uart *uart, speed_t baud) +{ + rtems_unsigned32 rate; + rtems_signed16 div; + int n; + rtems_unsigned32 Pph = sh4uart_get_Pph(); + + switch (baud) + { + case B50: rate = 50; break; + case B75: rate = 75; break; + case B110: rate = 110; break; + case B134: rate = 134; break; + case B150: rate = 150; break; + case B200: rate = 200; break; + case B300: rate = 300; break; + case B600: rate = 600; break; + case B1200: rate = 1200; break; + case B2400: rate = 2400; break; + case B4800: rate = 4800; break; + case B9600: rate = 9600; break; + case B19200: rate = 19200; break; + case B38400: rate = 38400; break; + case B57600: rate = 57600; break; +#ifdef B115200 + case B115200: rate = 115200; break; +#endif +#ifdef B230400 + case B230400: rate = 230400; break; +#endif + default: rate = 9600; break; + } + + for (n = 0; n < 4; n++) + { + div = Pph / (32 * (1 << (2 * n)) * rate) - 1; + if (div < 0x100) + break; + } + + /* Set default baudrate if specified baudrate is impossible */ + if (n >= 4) + sh4uart_set_baudrate(uart, B9600); + + SCSMR(uart->chn) &= ~SH7750_SCSMR_CKS; + SCSMR(uart->chn) |= n << SH7750_SCSMR_CKS_S; + SCBRR(uart->chn) = div; + /* Whait at least 1 bit interwal */ + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate)); +} + +/* + * sh4uart_reset -- + * This function perform the hardware initialization of SH-4 + * on-chip UART controller using parameters + * filled by the sh4uart_init function. + * + * PARAMETERS: + * uart - pointer to UART channel descriptor structure + * + * RETURNS: + * RTEMS_SUCCESSFUL if channel is initialized successfully, error + * code in other case + */ +rtems_status_code +sh4uart_reset(sh4uart *uart) +{ + register int chn; + register int int_driven; + rtems_status_code rc; + + if (uart == NULL) + return RTEMS_INVALID_ADDRESS; + + chn = uart->chn; + int_driven = uart->int_driven; + + SCSCR(chn) = 0x0; /* Is set properly at the end of this function */ + SCSMR(chn) = 0x0; /* 8-bit, non-parity, 1 stop bit, pf/1 clock */ + + if (chn == SH4_SCIF) + SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST | + SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4; + + if (chn == SH4_SCI) + SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO; + else + SCSPTR2 = SH7750_SCSPTR2_RTSDT; + + if (int_driven) + { + rtems_unsigned16 ipr; + + if (chn == SH4_SCI) + { + ipr = IPRB; + ipr &= ~SH7750_IPRB_SCI1; + ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S; + IPRB = ipr; + + rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit, + SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI), + &uart->old_handler_transmit); + if (rc != RTEMS_SUCCESSFUL) + return rc; + rc = rtems_interrupt_catch(sh4uart1_interrupt_receive, + SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI), + &uart->old_handler_receive); + if (rc != RTEMS_SUCCESSFUL) + return rc; + } + else + { + ipr = IPRC; + ipr &= ~SH7750_IPRC_SCIF; + ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S; + IPRC = ipr; + + rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit, + SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI), + &uart->old_handler_transmit); + if (rc != RTEMS_SUCCESSFUL) + return rc; + rc = rtems_interrupt_catch(sh4uart2_interrupt_receive, + SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI), + &uart->old_handler_receive); + if (rc != RTEMS_SUCCESSFUL) + return rc; + } + uart->tx_buf = NULL; + uart->tx_ptr = uart->tx_buf_len = 0; + } + + sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately, + it is differ to termios default */ + + SCSCR(chn) = SH7750_SCSCR_TE | SH7750_SCSCR_RE | + (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) | + (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0); + + return RTEMS_SUCCESSFUL; +} + +/* + * sh4uart_disable -- + * This function disable the operations on SH-4 UART controller + * + * PARAMETERS: + * uart - pointer to UART channel descriptor structure + * + * RETURNS: + * RTEMS_SUCCESSFUL if UART closed successfuly, or error code in + * other case + */ +rtems_status_code +sh4uart_disable(sh4uart *uart) +{ + rtems_status_code rc; + + SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); + + if (uart->int_driven) + { + rc = rtems_interrupt_catch(uart->old_handler_transmit, + uart->chn == SH4_SCI ? + SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI, + NULL); + if (rc != RTEMS_SUCCESSFUL) + return rc; + rc = rtems_interrupt_catch(uart->old_handler_receive, + uart->chn == SH4_SCI ? + SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI, + NULL); + if (rc != RTEMS_SUCCESSFUL) + return rc; + } + + return RTEMS_SUCCESSFUL; +} + +/* + * sh4uart_set_attributes -- + * This function parse the termios attributes structure and perform + * the appropriate settings in hardware. + * + * PARAMETERS: + * uart - pointer to the UART descriptor structure + * t - pointer to termios parameters + * + * RETURNS: + * RTEMS_SUCCESSFUL + */ +rtems_status_code +sh4uart_set_attributes(sh4uart *uart, const struct termios *t) +{ + int level; + speed_t baud; + rtems_unsigned16 smr; + + smr = (rtems_unsigned16)(*(rtems_unsigned8 *)SH7750_SCSMR(uart->chn)); + + baud = cfgetospeed(t); + + /* Set flow control XXX*/ + if ((t->c_cflag & CRTSCTS) != 0) + { + } + + /* Set character size -- only 7 or 8 bit */ + switch (t->c_cflag & CSIZE) + { + case CS5: + case CS6: + case CS7: smr |= SH7750_SCSMR_CHR_7; break; + case CS8: smr &= ~SH7750_SCSMR_CHR_7; break; + } + + /* Set number of stop bits */ + if ((t->c_cflag & CSTOPB) != 0) + smr |= SH7750_SCSMR_STOP_2; + else + smr &= ~SH7750_SCSMR_STOP_2; + + /* Set parity mode */ + if ((t->c_cflag & PARENB) != 0) + { + smr |= SH7750_SCSMR_PE; + if ((t->c_cflag & PARODD) != 0) + smr |= SH7750_SCSMR_PM_ODD; + else + smr &= ~SH7750_SCSMR_PM_ODD; + } + else + smr &= ~SH7750_SCSMR_PE; + + rtems_interrupt_disable(level); + /* wait untill all data is transmitted */ + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100)); + /* disable operations */ + SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); + + sh4uart_set_baudrate(uart, baud); + SCSMR(uart->chn) = (rtems_unsigned8)smr; + + /* enable operations */ + SCSCR(uart->chn) |= SH7750_SCSCR_TE | SH7750_SCSCR_RE; + rtems_interrupt_enable(level); + + return RTEMS_SUCCESSFUL; +} + +/* + * sh4uart_handle_error -- + * Perfoms error (Overrun, Framing & Parity) handling + * + * PARAMETERS: + * uart - pointer to UART descriptor structure + * + * RETURNS: + * nothing + */ +void +sh4uart_handle_error(sh4uart *uart) +{ +#if 0 + int status_reg = SCSSR(uart->chn); +#endif + + if(uart->chn == SH4_SCI) + { + SCSSR1 &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER); + } + else + { + SCSSR2 &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER); + SCLSR2 &= ~(SH7750_SCLSR2_ORER); + } +} + +/* + * sh4uart_poll_read -- + * This function tried to read character from SH-4 UART and perform + * error handling. When parity or framing error occured, return + * value dependent on termios input mode flags: + * - received character, if IGNPAR == 1 + * - 0, if IGNPAR == 0 and PARMRK == 0 + * - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and + * PARMRK == 1 + * + * PARAMETERS: + * uart - pointer to UART descriptor structure + * + * RETURNS: + * code of received character or -1 if no characters received. + */ +int +sh4uart_poll_read(sh4uart *uart) +{ + int chn = uart->chn; + int error_occured = 0; + int parity_error = 0; + int break_occured = 0; + int ch; + + if (uart->parerr_mark_flag == 1) + { + uart->parerr_mark_flag = 0; + return 0; + } + + if (chn == SH4_SCI) + { + if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER | + SH7750_SCSSR1_ORER)) != 0) + { + error_occured = 1; + if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) + parity_error = 1; + sh4uart_handle_error(uart); + } + if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0) + return -1; + } + else + { + if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR | + SH7750_SCSSR2_BRK)) != 0 || + (SCLSR2 & SH7750_SCLSR2_ORER) != 0) + { + error_occured = 1; + if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) + parity_error = 1; + if (SCSSR2 & SH7750_SCSSR2_BRK) + break_occured = 1; + sh4uart_handle_error(uart); + } + if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0) + return -1; + } + + if (parity_error && !(uart->c_iflag & IGNPAR)) + { + if (uart->c_iflag & PARMRK) + { + uart->parerr_mark_flag = 1; + return 0xff; + } + else + return 0; + } + + if (break_occured && !(uart->c_iflag & BRKINT)) + { + if (uart->c_iflag & IGNBRK) + return 0; + else + return 0; /* XXX -- SIGINT */ + } + + ch = SCRDR(chn); + if (uart->chn == SH4_SCI) + SCSSR1 &= ~SH7750_SCSSR1_RDRF; + else + SCSSR2 &= ~SH7750_SCSSR2_RDF; + + return ch; +} + +/* + * sh4uart_poll_write -- + * This function transmit buffer byte-by-byte in polling mode. + * + * PARAMETERS: + * uart - pointer to the UART descriptor structure + * buf - pointer to transmit buffer + * len - transmit buffer length + * + * RETURNS: + * 0 + */ +int +sh4uart_poll_write(sh4uart *uart, const char *buf, int len) +{ + while (len) + { + if (uart->chn == SH4_SCI) + { + while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0) + { + SCTDR1 = *buf++; + len--; + SCSSR1 &= ~SH7750_SCSSR1_TDRE; + } + } + else + { + while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) + { + int i; + for (i = 0; + i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & + SH7750_SCFCR2_TTRG); + i++) + { + SCTDR2 = *buf++; + len--; + } + while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 || + (SCSSR2 & SH7750_SCSSR2_TEND) == 0); + SCSSR2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND); + } + } + } + return 0; +} + +/********************************** + * Functions to handle interrupts * + **********************************/ +/* sh4uart1_interrupt_receive -- + * UART interrupt handler routine -- SCI + * Receiving data + * + * PARAMETERS: + * vec - interrupt vector number + * + * RETURNS: + * none + */ +static rtems_isr +sh4uart1_interrupt_receive(rtems_vector_number vec) +{ + register int bp = 0; + char buf[32]; + + /* Find UART descriptor from vector number */ + sh4uart *uart = &sh4_uarts[0]; + + while (1) + { + if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) + { + /* Receive character and handle frame/parity errors */ + if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER | + SH7750_SCSSR1_ORER)) != 0) + { + if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) + { + if(!(uart->c_iflag & IGNPAR)) + { + if (uart->c_iflag & PARMRK) + { + buf[bp++] = 0xff; + buf[bp++] = 0x00; + } + else + buf[bp++] = 0x00; + } + else + buf[bp++] = SCRDR1; + } + sh4uart_handle_error(uart); + } + else + buf[bp++] = SCRDR1; + SCSSR1 &= ~SH7750_SCSSR1_RDRF; + } + else + { + if (bp != 0) + rtems_termios_enqueue_raw_characters(uart->tty, buf, bp); + break; + } + } +} + +/* sh4uart2_interrupt_receive -- + * UART interrupt handler routine -- SCIF + * Receiving data + * + * PARAMETERS: + * vec - interrupt vector number + * + * RETURNS: + * none + */ +static rtems_isr +sh4uart2_interrupt_receive(rtems_vector_number vec) +{ + register int bp = 0; + char buf[32]; + + /* Find UART descriptor from vector number */ + sh4uart *uart = &sh4_uarts[1]; + + while (1) + { + if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0)) + { + if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR | + SH7750_SCSSR2_BRK)) != 0 || + (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0) + { + if (SCSSR2 & SH7750_SCSSR2_ER) + { + if(!(uart->c_iflag & IGNPAR)) + { + if (uart->c_iflag & PARMRK) + { + buf[bp++] = 0xff; + buf[bp++] = 0x00; + } + else + buf[bp++] = 0x00; + } + else + buf[bp++] = SCRDR1; + } + + if (SCSSR2 & SH7750_SCSSR2_BRK) + { + if (uart->c_iflag & IGNBRK) + buf[bp++] = 0x00; + else + buf[bp++] = 0x00; /* XXX -- SIGINT */ + } + + sh4uart_handle_error(uart); + } + else + buf[bp++] = SCRDR1; + SCSSR2 &= ~SH7750_SCSSR2_RDF; + } + else + { + if (bp != 0) + rtems_termios_enqueue_raw_characters(uart->tty, buf, bp); + break; + } + } +} + + +/* sh4uart1_interrupt_transmit -- + * UART interrupt handler routine -- SCI + * It continues transmit data when old part of data is transmitted + * + * PARAMETERS: + * vec - interrupt vector number + * + * RETURNS: + * none + */ +static rtems_isr +sh4uart1_interrupt_transmit(rtems_vector_number vec) +{ + /* Find UART descriptor from vector number */ + sh4uart *uart = &sh4_uarts[0]; + + if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) + { + while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 && + uart->tx_ptr < uart->tx_buf_len) + { + SCTDR1 = uart->tx_buf[uart->tx_ptr++]; + SCSSR1 &= ~SH7750_SCSSR1_TDRE; + } + } + else + { + register int dequeue = uart->tx_buf_len; + + uart->tx_buf = NULL; + uart->tx_ptr = uart->tx_buf_len = 0; + + /* Disable interrupts while we do not have any data to transmit */ + SCSCR1 &= ~SH7750_SCSCR_TIE; + + rtems_termios_dequeue_characters(uart->tty, dequeue); + } +} + +/* sh4uart2_interrupt_transmit -- + * UART interrupt handler routine -- SCI + * It continues transmit data when old part of data is transmitted + * + * PARAMETERS: + * vec - interrupt vector number + * + * RETURNS: + * none + */ +static rtems_isr +sh4uart2_interrupt_transmit(rtems_vector_number vec) +{ + /* Find UART descriptor from vector number */ + sh4uart *uart = &sh4_uarts[1]; + + if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) + { + while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) + { + int i; + for (i = 0; + i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & + SH7750_SCFCR2_TTRG); + i++) + SCTDR2 = uart->tx_buf[uart->tx_ptr++]; + while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 || + (SCSSR1 & SH7750_SCSSR1_TEND) == 0); + SCSSR1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND); + } + } + else + { + register int dequeue = uart->tx_buf_len; + + uart->tx_buf = NULL; + uart->tx_ptr = uart->tx_buf_len = 0; + + /* Disable interrupts while we do not have any data to transmit */ + SCSCR2 &= ~SH7750_SCSCR_TIE; + + rtems_termios_dequeue_characters(uart->tty, dequeue); + } +} + +/* sh4uart_interrupt_write -- + * This function initiate transmitting of the buffer in interrupt mode. + * + * PARAMETERS: + * uart - pointer to the UART descriptor structure + * buf - pointer to transmit buffer + * len - transmit buffer length + * + * RETURNS: + * 0 + */ +rtems_status_code +sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len) +{ + int level; + + while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0); + + rtems_interrupt_disable(level); + + uart->tx_buf = buf; + uart->tx_buf_len = len; + uart->tx_ptr = 0; + + if (uart->chn == SH4_SCI) + { + SCSCR1 |= SH7750_SCSCR_TIE; + } + else + SCSCR2 |= SH7750_SCSCR_TIE; + + rtems_interrupt_enable(level); + + return RTEMS_SUCCESSFUL; +} + +/* sh4uart_stop_remote_tx -- + * This function stop data flow from remote device. + * + * PARAMETERS: + * uart - pointer to the UART descriptor structure + * + * RETURNS: + * RTEMS_SUCCESSFUL + */ +rtems_status_code +sh4uart_stop_remote_tx(sh4uart *uart) +{ + SCSCR(uart->chn) &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE); + return RTEMS_SUCCESSFUL; +} + +/* sh4uart_start_remote_tx -- + * This function resume data flow from remote device. + * + * PARAMETERS: + * uart - pointer to the UART descriptor structure + * + * RETURNS: + * RTEMS_SUCCESSFUL + */ +rtems_status_code +sh4uart_start_remote_tx(sh4uart *uart) +{ + SCSCR(uart->chn) |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE; + return RTEMS_SUCCESSFUL; +} + +#ifdef SH4_WITH_IPL +/********************************* + * Functions for SH-IPL gdb stub * + *********************************/ + +/* + * ipl_finish -- + * Says gdb that program finished to get out from it. + */ +extern void ipl_finish(void); +asm( +" .global _ipl_finish\n" +"_ipl_finish:\n" +" mov.l __ipl_finish_value, r0\n" +" trapa #0x3f\n" +" nop\n" +" rts\n" +" nop\n" +" .align 4\n" +"__ipl_finish_value:\n" +" .long 255" +); + +extern int ipl_serial_input(int poll_count); +asm( +" .global _ipl_serial_input\n" +"_ipl_serial_input:\n" +" mov #1,r0\n" +" trapa #0x3f\n" +" nop\n" +" rts\n" +" nop\n"); + +extern void ipl_serial_output(const char *buf, int len); +asm ( +" .global _ipl_serial_output\n" +"_ipl_serial_output:\n" +" mov #0,r0\n" +" trapa #0x3f\n" +" nop\n" +" rts\n" +" nop\n"); + +/* ipl_console_poll_read -- + * poll read operation for simulator console through ipl mechanism. + * + * PARAMETERS: + * minor - minor device number + * + * RETURNS: + * character code red from UART, or -1 if there is no characters + * available + */ +int +ipl_console_poll_read(int minor) +{ + unsigned char buf; + buf = ipl_serial_input(0x100000); + return buf; +} + +/* ipl_console_poll_write -- + * wrapper for polling mode write function + * + * PARAMETERS: + * minor - minor device number + * buf - output buffer + * len - output buffer length + * + * RETURNS: + * result code (0) + */ +int +ipl_console_poll_write(int minor, const char *buf, int len) +{ + int c; + while (len > 0) + { + c = (len < 64 ? len : 64); + ipl_serial_output(buf, c); + len -= c; + buf += c; + } + return 0; +} +#endif -- cgit v1.2.3