source: rtems/c/src/lib/libcpu/sh/sh7750/sci/sh4uart.c @ 694debe

4.115
Last change on this file since 694debe was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 23.6 KB
Line 
1/*
2 * Generic UART Serial driver for SH-4 processors
3 *
4 * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
5 * Author: Alexandra Kossovsky <sasha@oktet.ru>
6 *
7 *  COPYRIGHT (c) 1989-2000.
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *  http://www.rtems.org/license/LICENSE.
13 *
14 */
15
16#include <rtems.h>
17#include <termios.h>
18#include <rtems/libio.h>
19#include <bsp.h>
20#include "sh/sh4uart.h"
21
22#ifndef SH4_UART_INTERRUPT_LEVEL
23#define SH4_UART_INTERRUPT_LEVEL 4
24#endif
25
26/* Forward function declarations */
27static rtems_isr
28sh4uart1_interrupt_transmit(rtems_vector_number vec);
29static rtems_isr
30sh4uart1_interrupt_receive(rtems_vector_number vec);
31static rtems_isr
32sh4uart2_interrupt_transmit(rtems_vector_number vec);
33static rtems_isr
34sh4uart2_interrupt_receive(rtems_vector_number vec);
35
36/*
37 * sh4uart_init --
38 * This function verifies the input parameters and perform initialization
39 *     of the SH-4 on-chip UART descriptor structure.
40 *
41 * PARAMETERS:
42 *     uart - pointer to the UART channel descriptor structure
43 *     tty - pointer to termios structure
44 *     chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
45 *     int_driven - interrupt-driven (1) or polled (0) I/O mode
46 *
47 * RETURNS:
48 *     RTEMS_SUCCESSFUL if all parameters are valid, or error code
49 */
50rtems_status_code
51sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
52{
53  if (uart == NULL)
54    return RTEMS_INVALID_ADDRESS;
55
56  if ((chn != SH4_SCI) && (chn != SH4_SCIF))
57    return RTEMS_INVALID_NUMBER;
58
59  uart->chn = chn;
60  uart->tty = tty;
61  uart->int_driven = int_driven;
62
63#if 0
64  sh4uart_poll_write(uart, "init", 4);
65#endif
66  return RTEMS_SUCCESSFUL;
67}
68
69/*
70 * sh4uart_get_Pph --
71 *    Get current peripheral module clock.
72 *
73 * PARAMETERS: none;
74 *    Cpu clock is get from CPU_CLOCK_RATE_HZ marco
75 *    (defined in bspopts.h, included from bsp.h)
76 *
77 * RETURNS:
78 *    peripheral module clock in Hz.
79 */
80uint32_t
81sh4uart_get_Pph(void)
82{
83  uint16_t   frqcr = *(volatile uint16_t*)SH7750_FRQCR;
84  uint32_t   Pph = CPU_CLOCK_RATE_HZ;
85
86  switch (frqcr & SH7750_FRQCR_IFC) {
87    case SH7750_FRQCR_IFCDIV1: break;
88    case SH7750_FRQCR_IFCDIV2: Pph *= 2; break;
89    case SH7750_FRQCR_IFCDIV3: Pph *= 3; break;
90    case SH7750_FRQCR_IFCDIV4: Pph *= 4; break;
91    case SH7750_FRQCR_IFCDIV6: Pph *= 6; break;
92    case SH7750_FRQCR_IFCDIV8: Pph *= 8; break;
93    default: /* unreachable */
94      break;
95  }
96
97  switch (frqcr & SH7750_FRQCR_PFC) {
98    case SH7750_FRQCR_PFCDIV2: Pph /= 2; break;
99    case SH7750_FRQCR_PFCDIV3: Pph /= 3; break;
100    case SH7750_FRQCR_PFCDIV4: Pph /= 4; break;
101    case SH7750_FRQCR_PFCDIV6: Pph /= 6; break;
102    case SH7750_FRQCR_PFCDIV8: Pph /= 8; break;
103    default: /* unreachable */
104      break;
105  }
106
107  return Pph;
108}
109
110/*
111 * sh4uart_set_baudrate --
112 *     Program the UART timer to specified baudrate
113 *
114 * PARAMETERS:
115 *     uart - pointer to UART descriptor structure
116 *     baud - termios baud rate (B50, B9600, etc...)
117 *
118 * ALGORITHM:
119 *     see SH7750 Hardware Manual.
120 *
121 * RETURNS:
122 *     none
123 */
124static void
125sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
126{
127  uint32_t   rate;
128  int16_t   div;
129  int n;
130  uint32_t   Pph = sh4uart_get_Pph();
131
132  switch (baud) {
133    case B50:     rate = 50; break;
134    case B75:     rate = 75; break;
135    case B110:    rate = 110; break;
136    case B134:    rate = 134; break;
137    case B150:    rate = 150; break;
138    case B200:    rate = 200; break;
139    case B300:    rate = 300; break;
140    case B600:    rate = 600; break;
141    case B1200:   rate = 1200; break;
142    case B2400:   rate = 2400; break;
143    case B4800:   rate = 4800; break;
144    case B9600:   rate = 9600; break;
145    case B19200:  rate = 19200; break;
146    case B38400:  rate = 38400; break;
147    case B57600:  rate = 57600; break;
148#ifdef B115200
149    case B115200: rate = 115200; break;
150#endif
151#ifdef B230400
152    case B230400: rate = 230400; break;
153#endif
154    default:      rate = 9600; break;
155  }
156
157  for (n = 0; n < 4; n++) {
158    div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
159    if (div < 0x100)
160      break;
161  }
162
163  /* Set default baudrate if specified baudrate is impossible */
164  if (n >= 4)
165    sh4uart_set_baudrate(uart, B9600);
166
167  if ( uart->chn == 1 ) {
168    volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
169    *smr1 &= ~SH7750_SCSMR_CKS;
170    *smr1 |= n << SH7750_SCSMR_CKS_S;
171  } else {
172    volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
173    *smr2 &= ~SH7750_SCSMR_CKS;
174    *smr2 |= n << SH7750_SCSMR_CKS_S;
175  }
176
177  SCBRR(uart->chn) = div;
178  /* Wait at least 1 bit interwal */
179  rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
180}
181
182/*
183 * sh4uart_reset --
184 *     This function perform the hardware initialization of SH-4
185 *     on-chip UART controller using parameters
186 *     filled by the sh4uart_init function.
187 *
188 * PARAMETERS:
189 *     uart - pointer to UART channel descriptor structure
190 *
191 * RETURNS:
192 *     RTEMS_SUCCESSFUL if channel is initialized successfully, error
193 *     code in other case
194 */
195rtems_status_code
196sh4uart_reset(sh4uart *uart)
197{
198  register int chn;
199  register int int_driven;
200  rtems_status_code rc;
201  uint16_t tmp;
202
203  if (uart == NULL)
204    return RTEMS_INVALID_ADDRESS;
205
206  chn = uart->chn;
207  int_driven = uart->int_driven;
208
209  if ( chn == 1 ) {
210    volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
211    volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
212    *scr1 = 0x0;       /* Is set properly at the end of this function */
213    *smr1 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
214  } else {
215    volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
216    volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
217    *scr2 = 0x0;       /* Is set properly at the end of this function */
218    *smr2 = 0x0;       /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
219  }
220
221  if (chn == SH4_SCIF)
222    SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
223             SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
224
225  if (chn == SH4_SCI)
226    SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
227  else
228    SCSPTR2 = SH7750_SCSPTR2_RTSDT;
229
230  if (int_driven) {
231    uint16_t   ipr;
232
233    if (chn == SH4_SCI) {
234      ipr = IPRB;
235      ipr &= ~SH7750_IPRB_SCI1;
236      ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
237      IPRB = ipr;
238
239      rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
240                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
241                                 &uart->old_handler_transmit);
242      if (rc != RTEMS_SUCCESSFUL)
243        return rc;
244
245      rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
246                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
247                                 &uart->old_handler_receive);
248      if (rc != RTEMS_SUCCESSFUL)
249        return rc;
250    } else {
251      ipr = IPRC;
252      ipr &= ~SH7750_IPRC_SCIF;
253      ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
254      IPRC = ipr;
255
256      rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
257                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
258                                 &uart->old_handler_transmit);
259      if (rc != RTEMS_SUCCESSFUL)
260        return rc;
261      rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
262                                 SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
263                                 &uart->old_handler_receive);
264      if (rc != RTEMS_SUCCESSFUL)
265        return rc;
266    }
267    uart->tx_buf = NULL;
268    uart->tx_ptr = uart->tx_buf_len = 0;
269  }
270
271  sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
272                                         it is differ to termios default */
273
274  tmp = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
275          (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
276          (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
277
278  if ( chn == 1 ) {
279    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
280    *scr = tmp;
281  } else {
282    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
283    *scr = tmp;
284  }
285
286  return RTEMS_SUCCESSFUL;
287}
288
289/*
290 * sh4uart_disable --
291 *     This function disable the operations on SH-4 UART controller
292 *
293 * PARAMETERS:
294 *     uart - pointer to UART channel descriptor structure
295 *     disable_port - disable receive and transmit on the port
296 *
297 * RETURNS:
298 *     RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
299 *     other case
300 */
301rtems_status_code
302sh4uart_disable(sh4uart *uart, int disable_port)
303{
304  rtems_status_code rc;
305
306  if (disable_port) {
307    if ( uart->chn == 1 ) {
308      volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
309      *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
310    } else {
311      volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
312      *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
313    }
314  }
315
316  if (uart->int_driven) {
317    rc = rtems_interrupt_catch(uart->old_handler_transmit,
318           uart->chn == SH4_SCI ?  SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
319           NULL);
320    if (rc != RTEMS_SUCCESSFUL)
321      return rc;
322    rc = rtems_interrupt_catch(uart->old_handler_receive,
323           uart->chn == SH4_SCI ?  SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
324           NULL);
325    if (rc != RTEMS_SUCCESSFUL)
326      return rc;
327  }
328
329  return RTEMS_SUCCESSFUL;
330}
331
332/*
333 * sh4uart_set_attributes --
334 *     This function parse the termios attributes structure and perform
335 *     the appropriate settings in hardware.
336 *
337 * PARAMETERS:
338 *     uart - pointer to the UART descriptor structure
339 *     t - pointer to termios parameters
340 *
341 * RETURNS:
342 *     RTEMS_SUCCESSFUL
343 */
344rtems_status_code
345sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
346{
347  int level;
348  speed_t baud;
349  uint16_t   smr;
350
351  smr = (uint16_t)(*(uint8_t*)SH7750_SCSMR(uart->chn));
352
353  baud = cfgetospeed(t);
354
355  /* Set flow control XXX*/
356  if ((t->c_cflag & CRTSCTS) != 0) {
357  }
358
359  /* Set character size -- only 7 or 8 bit */
360  switch (t->c_cflag & CSIZE) {
361    case CS5:
362    case CS6:
363    case CS7: smr |= SH7750_SCSMR_CHR_7; break;
364    case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
365  }
366
367    /* Set number of stop bits */
368  if ((t->c_cflag & CSTOPB) != 0)
369    smr |= SH7750_SCSMR_STOP_2;
370  else
371    smr &= ~SH7750_SCSMR_STOP_2;
372
373  /* Set parity mode */
374  if ((t->c_cflag & PARENB) != 0) {
375    smr |= SH7750_SCSMR_PE;
376    if ((t->c_cflag & PARODD) != 0)
377       smr |= SH7750_SCSMR_PM_ODD;
378    else
379       smr &= ~SH7750_SCSMR_PM_ODD;
380  } else
381    smr &= ~SH7750_SCSMR_PE;
382
383  rtems_interrupt_disable(level);
384  /* wait untill all data is transmitted */
385  /* XXX JOEL says this is broken -- interrupts are OFF so NO ticks  */
386  rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
387
388  if ( uart->chn == 1 ) {
389    volatile uint8_t *scrP = (volatile uint8_t *)SH7750_SCSCR1;
390    volatile uint8_t *smrP = (volatile uint8_t *)SH7750_SCSMR1;
391
392    *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
393    sh4uart_set_baudrate(uart, baud);
394    *smrP = (uint8_t)smr;
395    *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
396  } else {
397    volatile uint16_t *scrP = (volatile uint16_t *)SH7750_SCSCR2;
398    volatile uint16_t *smrP = (volatile uint16_t *)SH7750_SCSMR2;
399
400    *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
401    sh4uart_set_baudrate(uart, baud);
402    *smrP = (uint8_t)smr;
403    *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;    /* enable operations */
404  }
405
406  rtems_interrupt_enable(level);
407
408  return RTEMS_SUCCESSFUL;
409}
410
411/*
412 * sh4uart_handle_error --
413 *     Perfoms error (Overrun, Framing & Parity) handling
414 *
415 * PARAMETERS:
416 *     uart - pointer to UART descriptor structure
417 *
418 * RETURNS:
419 *     nothing
420 */
421void
422sh4uart_handle_error(sh4uart *uart)
423{
424  if (uart->chn == SH4_SCI) {
425    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
426    *scr &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
427  } else {
428    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
429    *scr &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
430    *scr &= ~(SH7750_SCLSR2_ORER);
431  }
432}
433
434/*
435 * sh4uart_poll_read --
436 *     This function tried to read character from SH-4 UART and perform
437 *     error handling. When parity or framing error occured, return
438 *     value dependent on termios input mode flags:
439 *         - received character, if IGNPAR == 1
440 *         - 0, if IGNPAR == 0 and PARMRK == 0
441 *         - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
442 *           PARMRK == 1
443 *
444 * PARAMETERS:
445 *     uart - pointer to UART descriptor structure
446 *
447 * RETURNS:
448 *     code of received character or -1 if no characters received.
449 */
450int
451sh4uart_poll_read(sh4uart *uart)
452{
453  int chn = uart->chn;
454  int error_occured = 0;
455  int parity_error = 0;
456  int break_occured = 0;
457  int ch;
458
459  if (uart->parerr_mark_flag == true) {
460    uart->parerr_mark_flag = false;
461    return 0;
462  }
463
464  if (chn == SH4_SCI) {
465    if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
466                 SH7750_SCSSR1_ORER)) != 0) {
467      error_occured = 1;
468      if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
469        parity_error = 1;
470      sh4uart_handle_error(uart);
471    }
472    if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
473      return -1;
474  } else {
475    if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
476                 SH7750_SCSSR2_BRK)) != 0 ||
477            (SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
478      error_occured = 1;
479      if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
480        parity_error = 1;
481      if (SCSSR2 & SH7750_SCSSR2_BRK)
482        break_occured = 1;
483      sh4uart_handle_error(uart);
484    }
485    if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
486      return -1;
487  }
488
489  if (parity_error && !(uart->c_iflag & IGNPAR)) {
490    if (uart->c_iflag & PARMRK) {
491      uart->parerr_mark_flag = true;
492      return 0xff;
493    } else
494      return 0;
495  }
496
497  if (break_occured && !(uart->c_iflag & BRKINT)) {
498    if (uart->c_iflag & IGNBRK)
499      return 0;
500    else
501      return 0;   /* XXX -- SIGINT */
502  }
503
504  ch = SCRDR(chn);
505
506  if (uart->chn == SH4_SCI) {
507    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
508    *scr &= ~SH7750_SCSSR1_RDRF;
509  } else {
510    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
511    *scr &= ~SH7750_SCSSR2_RDF;
512  }
513
514  return ch;
515}
516
517/*
518 * sh4uart_poll_write --
519 *     This function transmit buffer byte-by-byte in polling mode.
520 *
521 * PARAMETERS:
522 *     uart - pointer to the UART descriptor structure
523 *     buf - pointer to transmit buffer
524 *     len - transmit buffer length
525 *
526 * RETURNS:
527 *     0
528 */
529int
530sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
531{
532  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
533  volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
534
535  while (len) {
536    if (uart->chn == SH4_SCI) {
537      while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0) {
538          SCTDR1 = *buf++;
539          len--;
540          *ssr1 &= ~SH7750_SCSSR1_TDRE;
541      }
542    } else {
543      while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
544        int i;
545        for (i = 0;
546                i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
547                    SH7750_SCFCR2_TTRG);
548                i++) {
549            SCTDR2 = *buf++;
550            len--;
551        }
552        while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
553                (SCSSR2 & SH7750_SCSSR2_TEND) == 0);
554            *ssr2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
555      }
556    }
557  }
558  return 0;
559}
560
561/**********************************
562 * Functions to handle interrupts *
563 **********************************/
564/* sh4uart1_interrupt_receive --
565 *     UART interrupt handler routine -- SCI
566 *     Receiving data
567 *
568 * PARAMETERS:
569 *     vec - interrupt vector number
570 *
571 * RETURNS:
572 *     none
573 */
574static rtems_isr
575sh4uart1_interrupt_receive(rtems_vector_number vec)
576{
577  register int bp = 0;
578  char buf[32];
579  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
580
581
582  /* Find UART descriptor from vector number */
583  sh4uart *uart = &sh4_uarts[0];
584
585  while (1) {
586    if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) {
587      /* Receive character and handle frame/parity errors */
588      if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
589                      SH7750_SCSSR1_ORER)) != 0) {
590        if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) {
591            if (!(uart->c_iflag & IGNPAR)) {
592              if (uart->c_iflag & PARMRK) {
593                buf[bp++] = 0xff;
594                buf[bp++] = 0x00;
595              } else
596                buf[bp++] = 0x00;
597            } else
598              buf[bp++] = SCRDR1;
599          }
600          sh4uart_handle_error(uart);
601      } else
602          buf[bp++] = SCRDR1;
603      *ssr1 &= ~SH7750_SCSSR1_RDRF;
604    } else {
605      if (bp != 0)
606        rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
607      break;
608    }
609  }
610}
611
612/* sh4uart2_interrupt_receive --
613 *     UART interrupt handler routine -- SCIF
614 *     Receiving data
615 *
616 * PARAMETERS:
617 *     vec - interrupt vector number
618 *
619 * RETURNS:
620 *     none
621 */
622static rtems_isr
623sh4uart2_interrupt_receive(rtems_vector_number vec)
624{
625  register int bp = 0;
626  char buf[32];
627  volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
628
629
630  /* Find UART descriptor from vector number */
631  sh4uart *uart = &sh4_uarts[1];
632
633  while (1) {
634    if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0)) {
635      if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
636                      SH7750_SCSSR2_BRK)) != 0 ||
637              (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
638        if (SCSSR2 & SH7750_SCSSR2_ER) {
639          if (!(uart->c_iflag & IGNPAR)) {
640            if (uart->c_iflag & PARMRK) {
641              buf[bp++] = 0xff;
642              buf[bp++] = 0x00;
643            } else
644              buf[bp++] = 0x00;
645          } else
646              buf[bp++] = SCRDR1;
647        }
648
649        if (SCSSR2 & SH7750_SCSSR2_BRK) {
650          if (uart->c_iflag & IGNBRK)
651            buf[bp++] = 0x00;
652          else
653            buf[bp++] = 0x00;   /* XXX -- SIGINT */
654        }
655
656        sh4uart_handle_error(uart);
657      } else
658        buf[bp++] = SCRDR1;
659      *ssr2 &= ~SH7750_SCSSR2_RDF;
660    } else {
661      if (bp != 0)
662        rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
663      break;
664    }
665  }
666}
667
668
669/* sh4uart1_interrupt_transmit --
670 *     UART interrupt handler routine -- SCI
671 *     It continues transmit data when old part of data is transmitted
672 *
673 * PARAMETERS:
674 *     vec - interrupt vector number
675 *
676 * RETURNS:
677 *     none
678 */
679static rtems_isr
680sh4uart1_interrupt_transmit(rtems_vector_number vec)
681{
682  volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
683  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
684
685  /* Find UART descriptor from vector number */
686  sh4uart *uart = &sh4_uarts[0];
687
688  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
689    while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
690            uart->tx_ptr < uart->tx_buf_len) {
691        SCTDR1 = uart->tx_buf[uart->tx_ptr++];
692        *ssr1 &= ~SH7750_SCSSR1_TDRE;
693    }
694  } else {
695    register int dequeue = uart->tx_buf_len;
696
697    uart->tx_buf = NULL;
698    uart->tx_ptr = uart->tx_buf_len = 0;
699
700    /* Disable interrupts while we do not have any data to transmit */
701    *scr1 &= ~SH7750_SCSCR_TIE;
702
703    rtems_termios_dequeue_characters(uart->tty, dequeue);
704  }
705}
706
707/* sh4uart2_interrupt_transmit --
708 *     UART interrupt handler routine -- SCI
709 *     It continues transmit data when old part of data is transmitted
710 *
711 * PARAMETERS:
712 *     vec - interrupt vector number
713 *
714 * RETURNS:
715 *     none
716 */
717static rtems_isr
718sh4uart2_interrupt_transmit(rtems_vector_number vec)
719{
720  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
721  volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
722
723  /* Find UART descriptor from vector number */
724  sh4uart *uart = &sh4_uarts[1];
725
726  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
727    while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
728        int i;
729        for (i = 0;
730             i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & SH7750_SCFCR2_TTRG);
731             i++)
732          SCTDR2 = uart->tx_buf[uart->tx_ptr++];
733        while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
734                (SCSSR1 & SH7750_SCSSR1_TEND) == 0);
735        *ssr1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
736    }
737  } else {
738    register int dequeue = uart->tx_buf_len;
739
740    uart->tx_buf = NULL;
741    uart->tx_ptr = uart->tx_buf_len = 0;
742
743    /* Disable interrupts while we do not have any data to transmit */
744    *scr2 &= ~SH7750_SCSCR_TIE;
745
746    rtems_termios_dequeue_characters(uart->tty, dequeue);
747  }
748}
749
750/* sh4uart_interrupt_write --
751 *     This function initiate transmitting of the buffer in interrupt mode.
752 *
753 * PARAMETERS:
754 *     uart - pointer to the UART descriptor structure
755 *     buf - pointer to transmit buffer
756 *     len - transmit buffer length
757 *
758 * RETURNS:
759 *     0
760 */
761rtems_status_code
762sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
763{
764  if (len > 0) {
765    volatile uint8_t  *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
766    volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
767
768    while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
769
770    uart->tx_buf = buf;
771    uart->tx_buf_len = len;
772    uart->tx_ptr = 0;
773
774    if (uart->chn == SH4_SCI)
775      *scr1 |= SH7750_SCSCR_TIE;
776    else
777      *scr2 |= SH7750_SCSCR_TIE;
778  }
779
780  return RTEMS_SUCCESSFUL;
781}
782
783/* sh4uart_stop_remote_tx --
784 *     This function stop data flow from remote device.
785 *
786 * PARAMETERS:
787 *     uart - pointer to the UART descriptor structure
788 *
789 * RETURNS:
790 *     RTEMS_SUCCESSFUL
791 */
792rtems_status_code
793sh4uart_stop_remote_tx(sh4uart *uart)
794{
795  if ( uart->chn == 1 ) {
796    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
797    *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
798  } else {
799    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
800    *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
801  }
802
803  return RTEMS_SUCCESSFUL;
804}
805
806/* sh4uart_start_remote_tx --
807 *     This function resume data flow from remote device.
808 *
809 * PARAMETERS:
810 *     uart - pointer to the UART descriptor structure
811 *
812 * RETURNS:
813 *     RTEMS_SUCCESSFUL
814 */
815rtems_status_code
816sh4uart_start_remote_tx(sh4uart *uart)
817{
818  if ( uart->chn == 1 ) {
819    volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
820    *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
821  } else {
822    volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
823    *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
824  }
825
826  return RTEMS_SUCCESSFUL;
827}
828
829#ifdef SH4_WITH_IPL
830/*********************************
831 * Functions for SH-IPL gdb stub *
832 *********************************/
833
834/*
835 * ipl_finish --
836 *     Says gdb that program finished to get out from it.
837 */
838extern void ipl_finish(void);
839__asm__ (
840"   .global _ipl_finish\n"
841"_ipl_finish:\n"
842"   mov.l   __ipl_finish_value, r0\n"
843"   trapa   #0x3f\n"
844"   nop\n"
845"   rts\n"
846"   nop\n"
847"   .align 4\n"
848"__ipl_finish_value:\n"
849"   .long   255"
850);
851
852extern int ipl_serial_input(int poll_count);
853__asm__ (
854"    .global _ipl_serial_input\n"
855"_ipl_serial_input:\n"
856"    mov  #1,r0\n"
857"    trapa #0x3f\n"
858"    nop\n"
859"    rts\n"
860"    nop\n");
861
862extern void ipl_serial_output(const char *buf, int len);
863__asm__ (
864"    .global _ipl_serial_output\n"
865"_ipl_serial_output:\n"
866"    mov  #0,r0\n"
867"    trapa #0x3f\n"
868"    nop\n"
869"    rts\n"
870"    nop\n");
871
872/* ipl_console_poll_read --
873 *     poll read operation for simulator console through ipl mechanism.
874 *
875 * PARAMETERS:
876 *     minor - minor device number
877 *
878 * RETURNS:
879 *     character code red from UART, or -1 if there is no characters
880 *     available
881 */
882int
883ipl_console_poll_read(int minor)
884{
885    unsigned char buf;
886    buf = ipl_serial_input(0x100000);
887    return buf;
888}
889
890/* ipl_console_poll_write --
891 *     wrapper for polling mode write function
892 *
893 * PARAMETERS:
894 *     minor - minor device number
895 *     buf - output buffer
896 *     len - output buffer length
897 *
898 * RETURNS:
899 *     result code (0)
900 */
901int
902ipl_console_poll_write(int minor, const char *buf, int len)
903{
904  int c;
905  while (len > 0) {
906    c = (len < 64 ? len : 64);
907    ipl_serial_output(buf, c);
908    len -= c;
909    buf += c;
910  }
911  return 0;
912}
913#endif
Note: See TracBrowser for help on using the repository browser.