source: rtems/c/src/lib/libcpu/sh/sh7032/sci/sci.c @ c499856

4.115
Last change on this file since c499856 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: 7.4 KB
Line 
1/*
2 * /dev/sci[0|1] for Hitachi SH 703X
3 *
4 *  Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
5 *
6 *  COPYRIGHT (c) 1997-1999, Ralf Corsepius, Ulm, Germany
7 *
8 *  This program is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 *
13 *  COPYRIGHT (c) 1998.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.org/license/LICENSE.
19 */
20
21#include <rtems.h>
22
23#include <stdlib.h>
24
25#include <rtems/libio.h>
26#include <rtems/iosupp.h>
27#include <rtems/score/sh_io.h>
28#include <rtems/score/ispsh7032.h>
29#include <rtems/score/iosh7032.h>
30#include <sh/sh7_sci.h>
31#include <sh/sh7_pfc.h>
32#include <sh/sci.h>
33
34/*
35 * NOTE: Some SH variants have 3 sci devices
36 */
37
38#define SCI_MINOR_DEVICES       2
39
40#define SH_SCI_BASE_0   SCI0_SMR
41#define SH_SCI_BASE_1   SCI1_SMR
42
43struct scidev_t {
44  char *                        name ;
45  uint32_t                      addr ;
46  rtems_device_minor_number     minor ;
47  unsigned short                opened ;
48  tcflag_t                      cflags ;
49} sci_device[SCI_MINOR_DEVICES] =
50{
51  { "/dev/sci0", SH_SCI_BASE_0, 0, 0, B9600 | CS8 },
52  { "/dev/sci1", SH_SCI_BASE_1, 1, 0, B9600 | CS8 }
53} ;
54
55/*  imported from scitab.rel */
56extern int _sci_get_brparms(
57  tcflag_t      cflag,
58  unsigned char *smr,
59  unsigned char *brr );
60
61/* Translate termios' tcflag_t into sci settings */
62static int _sci_set_cflags(
63  struct scidev_t      *sci_dev,
64  tcflag_t      c_cflag )
65{
66  uint8_t       smr ;
67  uint8_t       brr ;
68
69  if ( c_cflag & CBAUD )
70  {
71    if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
72      return -1 ;
73  }
74
75  if ( c_cflag & CSIZE )
76  {
77    if ( c_cflag & CS8 )
78      smr &= ~SCI_SEVEN_BIT_DATA;
79    else if ( c_cflag & CS7 )
80      smr |= SCI_SEVEN_BIT_DATA;
81    else
82      return -1 ;
83  }
84
85  if ( c_cflag & CSTOPB )
86    smr |= SCI_STOP_BITS_2;
87  else
88    smr &= ~SCI_STOP_BITS_2;
89
90  if ( c_cflag & PARENB )
91    smr |= SCI_PARITY_ON ;
92  else
93    smr &= ~SCI_PARITY_ON ;
94
95  if ( c_cflag & PARODD )
96    smr |= SCI_ODD_PARITY ;
97  else
98    smr &= ~SCI_ODD_PARITY;
99
100  write8( smr, sci_dev->addr + SCI_SMR );
101  write8( brr, sci_dev->addr + SCI_BRR );
102
103  return 0 ;
104}
105
106static void _sci_init(
107  rtems_device_minor_number minor )
108{
109  uint16_t      temp16 ;
110
111  /* Pin function controller initialisation for asynchronous mode */
112  if( minor == 0)
113    {
114      temp16 = read16( PFC_PBCR1);
115      temp16 &= ~( PB8MD | PB9MD );
116      temp16 |= (PB_TXD0 | PB_RXD0);
117      write16( temp16, PFC_PBCR1);
118    }
119  else
120    {
121      temp16 = read16( PFC_PBCR1);
122      temp16 &= ~( PB10MD | PB11MD);
123      temp16 |= (PB_TXD1 | PB_RXD1);
124      write16( temp16, PFC_PBCR1);
125    }
126
127  /* disable sck-pin */
128  if( minor == 0)
129  {
130          temp16 = read16( PFC_PBCR1);
131          temp16 &= ~(PB12MD);
132          write16( temp16, PFC_PBCR1);
133  }
134  else
135  {
136          temp16 = read16( PFC_PBCR1);
137          temp16 &= ~(PB13MD);
138          write16( temp16, PFC_PBCR1);
139  }
140}
141
142static void _sci_tx_polled(
143  int minor,
144  const char buf )
145{
146  struct scidev_t *scidev = &sci_device[minor] ;
147  int8_t           ssr ;
148
149  while ( !inb((scidev->addr + SCI_SSR) & SCI_TDRE ))
150      ;
151  write8(buf,scidev->addr+SCI_TDR);
152
153  ssr = inb(scidev->addr+SCI_SSR);
154  ssr &= ~SCI_TDRE ;
155  write8(ssr,scidev->addr+SCI_SSR);
156}
157
158static int _sci_rx_polled (
159  int minor)
160{
161  struct scidev_t *scidev = &sci_device[minor] ;
162
163  unsigned char c;
164  char ssr ;
165  ssr = read8(scidev->addr + SCI_SSR) ;
166
167  if (ssr & (SCI_PER | SCI_FER | SCI_ORER))
168    write8(ssr & ~(SCI_PER | SCI_FER | SCI_ORER), scidev->addr+SCI_SSR);
169
170  if ( !(ssr & SCI_RDRF) )
171    return -1;
172
173  c = read8(scidev->addr + SCI_RDR) ;
174
175  write8(ssr & ~SCI_RDRF,scidev->addr + SCI_SSR);
176  return c;
177}
178
179/*
180 * sci_initialize
181 */
182
183rtems_device_driver sh_sci_initialize(
184  rtems_device_major_number  major,
185  rtems_device_minor_number  minor,
186  void                      *arg )
187{
188  rtems_device_driver status ;
189  rtems_device_minor_number     i;
190
191  /*
192   * register all possible devices.
193   * the initialization of the hardware is done by sci_open
194   */
195
196  for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
197  {
198    status = rtems_io_register_name(
199      sci_device[i].name,
200      major,
201      sci_device[i].minor );
202    if (status != RTEMS_SUCCESSFUL)
203      rtems_fatal_error_occurred(status);
204  }
205
206  /* default hardware setup */
207
208  return RTEMS_SUCCESSFUL;
209}
210
211
212/*
213 *  Open entry point
214 */
215
216rtems_device_driver sh_sci_open(
217  rtems_device_major_number major,
218  rtems_device_minor_number minor,
219  void                    * arg )
220{
221  uint8_t   temp8;
222
223 /* check for valid minor number */
224   if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
225   {
226     return RTEMS_INVALID_NUMBER;
227   }
228
229 /* device already opened */
230  if ( sci_device[minor].opened > 0 )
231  {
232    sci_device[minor].opened++ ;
233    return RTEMS_SUCCESSFUL ;
234  }
235
236  _sci_init( minor );
237
238  if (minor == 0) {
239    temp8 = read8(sci_device[minor].addr + SCI_SCR);
240    temp8 &= ~(SCI_TE | SCI_RE) ;
241    write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
242    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );
243
244/* FIXME: Should be one bit delay */
245    CPU_delay(50000); /* microseconds */
246
247    temp8 |= SCI_RE | SCI_TE;
248    write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Enable clock output */
249  } else {
250    temp8 = read8(sci_device[minor].addr + SCI_SCR);
251    temp8 &= ~(SCI_TE | SCI_RE) ;
252    write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
253    _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags );
254
255/* FIXME: Should be one bit delay */
256    CPU_delay(50000); /* microseconds */
257
258    temp8 |= SCI_RE | SCI_TE;
259    write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Enable clock output */
260  }
261
262  sci_device[minor].opened++ ;
263
264  return RTEMS_SUCCESSFUL ;
265}
266
267/*
268 *  Close entry point
269 */
270
271rtems_device_driver sh_sci_close(
272  rtems_device_major_number major,
273  rtems_device_minor_number minor,
274  void                    * arg
275)
276{
277  if( sci_device[minor].opened == 0 )
278    {
279      return RTEMS_INVALID_NUMBER;
280    }
281
282  sci_device[minor].opened-- ;
283
284  return RTEMS_SUCCESSFUL ;
285}
286
287/*
288 * read bytes from the serial port.
289 */
290
291rtems_device_driver sh_sci_read(
292  rtems_device_major_number major,
293  rtems_device_minor_number minor,
294  void                    * arg
295)
296{
297  int count = 0;
298
299  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
300  char * buffer = rw_args->buffer;
301  int maximum = rw_args->count;
302
303  for (count = 0; count < maximum; count++) {
304    buffer[ count ] = _sci_rx_polled(minor);
305    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
306      buffer[ count++ ]  = '\n';
307      break;
308    }
309  }
310
311  rw_args->bytes_moved = count;
312  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
313}
314
315/*
316 * write bytes to the serial port.
317 */
318
319rtems_device_driver sh_sci_write(
320  rtems_device_major_number major,
321  rtems_device_minor_number minor,
322  void                    * arg
323)
324{
325  int count;
326
327  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
328  char *buffer = rw_args->buffer;
329  int maximum = rw_args->count;
330
331  for (count = 0; count < maximum; count++) {
332#if 0
333    if ( buffer[ count ] == '\n') {
334      outbyte(minor, '\r');
335    }
336#endif
337    _sci_tx_polled( minor, buffer[ count ] );
338  }
339
340  rw_args->bytes_moved = maximum;
341  return 0;
342}
343
344/*
345 *  IO Control entry point
346 */
347
348rtems_device_driver sh_sci_control(
349  rtems_device_major_number major,
350  rtems_device_minor_number minor,
351  void                    * arg
352)
353{
354  /* Not yet supported */
355  return RTEMS_SUCCESSFUL ;
356}
Note: See TracBrowser for help on using the repository browser.