OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [lib/] [libcpu/] [sh/] [sh7045/] [sci/] [sci.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.