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

4.11
Last change on this file since 82f5ec4 was 82f5ec4, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 20, 2014 at 4:31:41 PM

libcpu/sh/sh7045/sci/sci.c: Eliminate use of obsolete method

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