source: rtems/c/src/lib/libcpu/sh/sh7045/sci/sci.c @ f30a0ca9

4.104.114.84.95
Last change on this file since f30a0ca9 was 7ae5125, checked in by Joel Sherrill <joel.sherrill@…>, on 08/16/01 at 21:08:28

2001-08-10 Radzislaw Galler <rgaller@…>

  • score/cpu_asm.c (sh_set_irq_priority): Changed interrupt vector number range check and handling of interrupt priority regs to conform SH2 specs.
  • sci/sci_termios.c: New file.
  • include/sci_termios.h: New file.
  • include/Makefile.am (EXTRA_DIST): Added sci_termios.h. (include_sh_HEADERS): Added sci_termios.h.
  • score/ispsh7045.c (isp): Calling an ISR with immediate argument casued negative sign extension for vector numbers of 128 and above. This was fixed.
  • sci/sci.c: Cleaned initialization of SCI registers; added necessary setup for new TERMIOS console cooperation
  • Property mode set to 100644
File size: 13.6 KB
Line 
1/*
2 * /dev/sci[0|1] for Hitachi SH 704X
3 *
4 * The SH doesn't have a designated console device. Therefore we "alias"
5 * another device as /dev/console and revector all calls to /dev/console
6 * to this device.
7 *
8 * This approach is similar to installing a sym-link from one device to
9 * another device. If rtems once will support sym-links for devices files,
10 * this implementation could be dropped.
11 *
12 *  Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
13 *
14 *  COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 *
21 *  COPYRIGHT (c) 1998.
22 *  On-Line Applications Research Corporation (OAR).
23 *  Copyright assigned to U.S. Government, 1994.
24 *
25 *  The license and distribution terms for this file may be
26 *  found in the file LICENSE in this distribution or at
27 *  http://www.OARcorp.com/rtems/license.html.
28 *
29 *  Modified to reflect sh7045 processor:
30 *  John M. Mills (jmills@tga.com)
31 *  TGA Technologies, Inc.
32 *  100 Pinnacle Way, Suite 140
33 *  Norcross, GA 30071 U.S.A.
34 *
35 *  This modified file may be copied and distributed in accordance
36 *  the above-referenced license. It is provided for critique and
37 *  developmental purposes without any warranty nor representation
38 *  by the authors or by TGA Technologies.
39 *
40 *  $Id$
41 */
42
43#include <rtems.h>
44
45
46#include <stdlib.h>
47
48#include <rtems/libio.h>
49#include <iosupp.h>
50#include <rtems/score/sh_io.h>
51#include <rtems/score/ispsh7045.h>
52#include <rtems/score/iosh7045.h>
53#include <sh/sh7_sci.h>
54#include <sh/sh7_pfc.h>
55
56#include <sh/sci.h>
57
58#ifndef STANDALONE_EVB
59#define STANDALONE_EVB 0
60#endif
61
62/*
63 * NOTE: Some SH variants have 3 sci devices
64 */
65 
66#define SCI_MINOR_DEVICES       2
67 
68/*
69 * FIXME: sh7045 register names match Hitachi data book,
70 *  but conflict with RTEMS sh7032 usage.
71 */
72
73#define SH_SCI_BASE_0   SCI_SMR0
74#define SH_SCI_BASE_1   SCI_SMR1
75
76#define SH_SCI_DEF_COMM_0   B9600 | CS8
77#define SH_SCI_DEF_COMM_1   B38400 | CS8
78/*  #define SH_SCI_DEF_COMM_1   B9600 | CS8 */
79
80struct scidev_t {
81  char *                        name ;
82  unsigned32                    addr ;
83  rtems_device_minor_number     minor ;
84  unsigned short                opened ;
85  tcflag_t                      cflags ;
86} sci_device[SCI_MINOR_DEVICES] =
87{
88  { "/dev/sci0", SH_SCI_BASE_0, 0, 0, SH_SCI_DEF_COMM_0 },
89  { "/dev/sci1", SH_SCI_BASE_1, 1, 0, SH_SCI_DEF_COMM_1 }
90} ;
91
92/*  local data structures maintain hardware configuration */
93#if UNUSED
94static sci_setup_t sio_param[2];
95#endif
96
97/*  imported from scitab.rel */
98extern int _sci_get_brparms(
99  tcflag_t      cflag,
100  unsigned char *smr,
101  unsigned char *brr );
102
103/* Translate termios' tcflag_t into sci settings */
104static int _sci_set_cflags(
105  struct scidev_t      *sci_dev,
106  tcflag_t      c_cflag )
107{
108  unsigned8     smr ;
109  unsigned8     brr ;
110 
111  if ( c_cflag & CBAUD )
112  {
113    if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
114      return -1 ;
115  }
116                   
117  if ( c_cflag & CSIZE )
118  {
119    if ( c_cflag & CS8 )
120      smr &= ~SCI_SEVEN_BIT_DATA;
121    else if ( c_cflag & CS7 )
122      smr |= SCI_SEVEN_BIT_DATA;
123    else
124      return -1 ;
125  }
126
127  if ( c_cflag & CSTOPB )
128    smr |= SCI_STOP_BITS_2;
129  else
130    smr &= ~SCI_STOP_BITS_2;
131
132  if ( c_cflag & PARENB )
133    smr |= SCI_PARITY_ON ;
134  else
135    smr &= ~SCI_PARITY_ON ;
136
137  if ( c_cflag & PARODD )
138    smr |= SCI_ODD_PARITY ;
139  else
140    smr &= ~SCI_ODD_PARITY;
141   
142  write8( smr, sci_dev->addr + SCI_SMR );
143  write8( brr, sci_dev->addr + SCI_BRR );
144 
145  return 0 ;
146}
147
148/*
149 * local functions operate SCI ports 0 and 1
150 * called from polling routines or ISRs
151 */
152rtems_boolean wrtSCI0(unsigned char ch)
153{
154  unsigned8 temp;
155  rtems_boolean result=FALSE;
156
157  if ((read8(SCI_SSR0) & SCI_TDRE) != 0x00) {
158    /* Write the character to the TDR */
159    write8(ch, SCI_TDR0);
160    /* Clear the TDRE bit */
161    temp = read8(SCI_SSR0) & ~SCI_TDRE;
162    write8(temp, SCI_SSR0);
163    result = TRUE;
164  }
165  return result;
166} /* wrtSCI0 */
167
168rtems_boolean wrtSCI1(unsigned char ch)
169{
170  unsigned8 temp;
171  rtems_boolean result=FALSE;
172
173  if ((read8(SCI_SSR1) & SCI_TDRE) != 0x00) {
174     /* Write the character to the TDR */
175     write8(ch, SCI_TDR1);
176     /* Clear the TDRE bit */
177     temp = read8(SCI_SSR1) & ~SCI_TDRE;
178     write8(temp, SCI_SSR1);
179     result = TRUE;
180  }
181  return result;
182} /* wrtSCI1 */
183
184/* polled output steers byte to selected port */
185void sh_sci_outbyte_polled(
186  rtems_device_minor_number  minor,
187  char ch )
188{
189        if (minor == 0) /* blocks until port ready */
190                while (wrtSCI0(ch) != TRUE); /* SCI0*/
191        else
192                while (wrtSCI1(ch) != TRUE); /* SCI1*/
193} /* sh_sci_outbyte_polled */
194
195/*
196 * Initial version calls polled output driver and blocks
197 */
198void outbyte(
199  rtems_device_minor_number  minor,
200  char ch)
201{
202        sh_sci_outbyte_polled(minor, (unsigned char)ch);
203} /* outbyte */
204
205rtems_boolean rdSCI0(unsigned char *ch)
206{
207  unsigned8 temp;
208  rtems_boolean result=FALSE;
209
210  if ((read8(SCI_SSR0) & SCI_RDRF) != 0x00) {
211    /* read input */
212    *ch = read8(SCI_RDR0);
213    /* Clear RDRF flag */
214    temp = read8(SCI_SSR0) & ~SCI_RDRF;
215    write8(temp, SCI_SSR0);
216    /* Check for transmission errors */
217    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){
218        /* TODO: report to RTEMS transmission error */
219
220        /* clear error flags*/
221        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
222        write8(temp, SCI_SSR0);
223    }
224    result = TRUE;
225  }
226  return result;
227} /* rdSCI0 */
228
229rtems_boolean rdSCI1(unsigned char *ch)
230{
231  unsigned8 temp;
232  rtems_boolean result=FALSE;
233
234  if ((read8(SCI_SSR1) & SCI_RDRF) != 0x00) {
235    /* read input */
236    *ch = read8(SCI_RDR1);
237    /* Clear RDRF flag */
238    temp= read8(SCI_SSR1) & ~SCI_RDRF;
239    write8(temp, SCI_SSR1);
240    /* Check for transmission errors */
241    if(temp & (SCI_ORER | SCI_FER | SCI_PER)){
242        /* TODO: report to RTEMS transmission error */
243
244        /* clear error flags*/
245        temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
246        write8(temp, SCI_SSR1);
247    }
248    result = TRUE;
249  }
250  return result;
251} /* rdSCI1 */
252
253
254/* initial version pulls byte from selected port */
255char sh_sci_inbyte_polled(
256    rtems_device_minor_number  minor )
257{
258        char ch;
259       
260        if (minor == 0) /* blocks until char.ready */
261                while (rdSCI0(&ch) != TRUE); /* SCI0 */
262        else
263                while (rdSCI1(&ch) != TRUE); /* SCI1 */
264        return ch;
265} /* sh_sci_inbyte_polled */
266
267/* Initial version calls polled input driver */
268char inbyte(
269  rtems_device_minor_number  minor )
270{
271        char ch;
272
273        ch = sh_sci_inbyte_polled(minor);
274        return ch;
275} /* inbyte */
276
277
278/*  sh_sci_initialize
279 *
280 *  This routine initializes (registers) the sh_sci IO drivers.
281 *
282 *  Input parameters: ignored
283 *
284 *  Output parameters:  NONE
285 *
286 *  Return values: RTEMS_SUCCESSFUL
287 *   if all sci[...] register, else calls
288 *   rtems_fatal_error_occurred(status)
289 *
290 */
291
292rtems_device_driver sh_sci_initialize(
293  rtems_device_major_number  major,
294  rtems_device_minor_number  minor,
295  void                      *arg )
296{
297  rtems_device_driver status ;
298  rtems_device_minor_number i;
299  rtems_driver_name_t *driver = NULL;
300 
301 
302  /*
303   * register all possible devices.
304   * the initialization of the hardware is done by sci_open
305   *
306   * One of devices could be previously registered by console
307   * initialization therefore we check it everytime
308   */
309
310  for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
311  {
312    status = rtems_io_lookup_name(
313        sci_device[i].name,
314        &driver);
315    if( status != RTEMS_SUCCESSFUL )
316    {
317        /* OK. We assume it is not registered yet. */
318        status = rtems_io_register_name(
319            sci_device[i].name,
320            major,
321            sci_device[i].minor );
322        if (status != RTEMS_SUCCESSFUL)
323            rtems_fatal_error_occurred(status);
324    }
325  }
326
327  /* non-default hardware setup occurs in sh_sci_open() */
328
329  return RTEMS_SUCCESSFUL;
330}
331
332
333/*
334 *  Open entry point
335 *   Sets up port and pins for selected sci.
336 */
337
338rtems_device_driver sh_sci_open(
339  rtems_device_major_number major,
340  rtems_device_minor_number minor,
341  void                    * arg )
342{
343  unsigned8 temp8;
344  unsigned16 temp16;
345 
346  unsigned      a ;
347 
348 /* check for valid minor number */
349   if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
350   {
351     return RTEMS_INVALID_NUMBER;
352   }
353 
354  /* device already opened */
355  if ( sci_device[minor].opened > 0 )
356  {
357    sci_device[minor].opened++ ;
358    return RTEMS_SUCCESSFUL ;
359  }
360   
361  /* set PFC registers to enable I/O pins */
362
363  if ((minor == 0)) {
364    temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */
365    temp16 &= ~(PA2MD1 | PA2MD0);
366    temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */
367    write16(temp16, PFC_PACRL2);
368   
369  } else if (minor == 1) { 
370    temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */
371    temp16 &= ~(PA5MD1 | PA5MD0);
372    temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */
373    write16(temp16, PFC_PACRL2);
374
375  } /* add other devices and pins as req'd. */
376
377  /* set up SCI registers */
378      write8(0x00, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
379                                                   /* set SMR and BRR */
380    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );
381
382    for(a=0; a < 10000L; a++) {                      /* Delay */
383      asm volatile ("nop");
384    }
385
386    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */
387           sci_device[minor].addr + SCI_SCR);
388
389    /* clear error flags */
390    temp8 = read8(sci_device[minor].addr + SCI_SSR);
391    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)){
392        temp8 = read8(sci_device[minor].addr + SCI_RDR);   /* flush input */
393        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* clear some flags */
394        write8(temp8 & ~(SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER),
395               sci_device[minor].addr + SCI_SSR);
396        temp8 = read8(sci_device[minor].addr + SCI_SSR); /* check if everything is OK */
397    }   
398    /* Clear RDRF flag */
399    write8(0x00, sci_device[minor].addr + SCI_TDR);    /* force output */
400     /* Clear the TDRE bit */
401     temp8 = read8(sci_device[minor].addr + SCI_SSR) & ~SCI_TDRE;
402     write8(temp8, sci_device[minor].addr + SCI_SSR);
403   
404    /* add interrupt setup if required */
405
406 
407  sci_device[minor].opened++ ;
408
409  return RTEMS_SUCCESSFUL ;
410}
411 
412/*
413 *  Close entry point
414 */
415
416rtems_device_driver sh_sci_close(
417  rtems_device_major_number major,
418  rtems_device_minor_number minor,
419  void                    * arg
420)
421{
422  /* FIXME: Incomplete */
423  if ( sci_device[minor].opened > 0 )
424    sci_device[minor].opened-- ;
425  else
426    return RTEMS_INVALID_NUMBER ;
427   
428  return RTEMS_SUCCESSFUL ;
429}
430
431/*
432 * read bytes from the serial port. We only have stdin.
433 */
434
435rtems_device_driver sh_sci_read(
436  rtems_device_major_number major,
437  rtems_device_minor_number minor,
438  void                    * arg
439)
440{
441  rtems_libio_rw_args_t *rw_args;
442  char *buffer;
443  int maximum;
444  int count = 0;
445 
446  rw_args = (rtems_libio_rw_args_t *) arg;
447
448  buffer = rw_args->buffer;
449  maximum = rw_args->count;
450
451  for (count = 0; count < maximum; count++) {
452    buffer[ count ] = inbyte(minor);
453    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
454      buffer[ count++ ]  = '\n';
455      break;
456    }
457  }
458
459  rw_args->bytes_moved = count;
460  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
461}
462
463/*
464 * write bytes to the serial port. Stdout and stderr are the same.
465 */
466
467rtems_device_driver sh_sci_write(
468  rtems_device_major_number major,
469  rtems_device_minor_number minor,
470  void                    * arg
471)
472{
473  int count;
474  int maximum;
475  rtems_libio_rw_args_t *rw_args;
476  char *buffer;
477
478  rw_args = (rtems_libio_rw_args_t *) arg;
479
480  buffer = rw_args->buffer;
481  maximum = rw_args->count;
482
483  for (count = 0; count < maximum; count++) {
484    if ( buffer[ count ] == '\n') {
485      outbyte(minor, '\r');
486    }
487    outbyte( minor, buffer[ count ] );
488  }
489
490  rw_args->bytes_moved = maximum;
491  return 0;
492}
493
494/*
495 *  IO Control entry point
496 */
497
498rtems_device_driver sh_sci_control(
499  rtems_device_major_number major,
500  rtems_device_minor_number minor,
501  void                    * arg
502)
503{
504  /* Not yet supported */
505  return RTEMS_SUCCESSFUL ;
506}
507
508/*
509 * Termios polled first open
510 */
511static int _sh_sci_poll_first_open(int major, int minor, void *arg)
512{
513    return sh_sci_open(major, minor, arg);
514}
515
516/*
517 * Termios general last close
518 */
519static int _sh_sci_last_close(int major, int minor, void *arg)
520{
521    return sh_sci_close(major, minor, arg);
522}
523
524/*
525 * Termios polled read
526 */
527static int _sh_sci_poll_read(int minor)
528{
529    int value = -1;
530    char ch;
531   
532    if( minor == 0 ){
533        if( rdSCI0( &ch ) )
534            value = (int) ch;
535    }else if( minor == 1 ){
536        if( rdSCI1( &ch ) )
537            value = (int) ch;
538    }
539    return value;
540}
541
542/*
543 * Termios polled write
544 */
545static int _sh_sci_poll_write(int minor, const char *buf, int len)
546{
547    int count;
548   
549    for(count = 0; count < len; count++)
550        outbyte( minor, buf[count] );
551    return count;
552}
553
554/*
555 * Termios set attributes
556 */
557static int _sh_sci_set_attributes( int minor, const struct termios *t)
558{
559    return _sci_set_cflags( &sci_device[ minor ], t->c_cflag);
560}
561
562
563const rtems_termios_callbacks sci_poll_callbacks = {
564    _sh_sci_poll_first_open,    /* FirstOpen*/
565    _sh_sci_last_close,         /* LastClose*/
566    _sh_sci_poll_read,          /* PollRead  */
567    _sh_sci_poll_write,         /* Write */
568    _sh_sci_set_attributes,     /* setAttributes */
569    NULL,                       /* stopRemoteTX */
570    NULL,                       /* StartRemoteTX */
571    0                           /* outputUsesInterrupts */
572};
573
574/* FIXME: not yet supported */
575const rtems_termios_callbacks sci_interrupt_callbacks;
576
577const rtems_termios_callbacks* sh_sci_get_termios_handlers( rtems_boolean poll )
578{
579    return poll ?
580        &sci_poll_callbacks :
581        &sci_interrupt_callbacks;
582}
Note: See TracBrowser for help on using the repository browser.