Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:01

0001 /*
0002  * /dev/sci[0|1] for Hitachi SH 703X
0003  *
0004  *  Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
0005  *
0006  *  COPYRIGHT (c) 1997-1999, Ralf Corsepius, Ulm, Germany
0007  *
0008  *  This program is distributed in the hope that it will be useful,
0009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0011  *
0012  *
0013  *  COPYRIGHT (c) 1998.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  *  The license and distribution terms for this file may be
0017  *  found in the file LICENSE in this distribution or at
0018  *  http://www.rtems.org/license/LICENSE.
0019  */
0020 
0021 #include <bsp.h>
0022 
0023 #include <stdlib.h>
0024 
0025 #include <rtems/libio.h>
0026 #include <rtems/iosupp.h>
0027 #include <rtems/score/sh_io.h>
0028 #include <rtems/score/ispsh7032.h>
0029 #include <rtems/score/iosh7032.h>
0030 #include <sh/sh7_sci.h>
0031 #include <sh/sh7_pfc.h>
0032 #include <sh/sci.h>
0033 
0034 /*
0035  * NOTE: Some SH variants have 3 sci devices
0036  */
0037 
0038 #define SCI_MINOR_DEVICES       2
0039 
0040 #define SH_SCI_BASE_0   SCI0_SMR
0041 #define SH_SCI_BASE_1   SCI1_SMR
0042 
0043 struct scidev_t {
0044   char *            name ;
0045   uint32_t              addr ;
0046   rtems_device_minor_number minor ;
0047   unsigned short        opened ;
0048   tcflag_t          cflags ;
0049   speed_t       spd ;
0050 } sci_device[SCI_MINOR_DEVICES] =
0051 {
0052   { "/dev/sci0", SH_SCI_BASE_0, 0, 0, CS8, B9600 },
0053   { "/dev/sci1", SH_SCI_BASE_1, 1, 0, CS8, B9600 }
0054 } ;
0055 
0056 /* Translate termios' tcflag_t into sci settings */
0057 static int _sci_set_cflags(
0058   struct scidev_t      *sci_dev,
0059   tcflag_t      c_cflag,
0060   speed_t       spd )
0061 {
0062   uint8_t   smr ;
0063   uint8_t   brr ;
0064 
0065   if ( spd )
0066   {
0067     if ( _sci_get_brparms( spd, &smr, &brr ) != 0 )
0068       return -1 ;
0069   }
0070 
0071   if ( c_cflag & CSIZE )
0072   {
0073     if ( c_cflag & CS8 )
0074       smr &= ~SCI_SEVEN_BIT_DATA;
0075     else if ( c_cflag & CS7 )
0076       smr |= SCI_SEVEN_BIT_DATA;
0077     else
0078       return -1 ;
0079   }
0080 
0081   if ( c_cflag & CSTOPB )
0082     smr |= SCI_STOP_BITS_2;
0083   else
0084     smr &= ~SCI_STOP_BITS_2;
0085 
0086   if ( c_cflag & PARENB )
0087     smr |= SCI_PARITY_ON ;
0088   else
0089     smr &= ~SCI_PARITY_ON ;
0090 
0091   if ( c_cflag & PARODD )
0092     smr |= SCI_ODD_PARITY ;
0093   else
0094     smr &= ~SCI_ODD_PARITY;
0095 
0096   write8( smr, sci_dev->addr + SCI_SMR );
0097   write8( brr, sci_dev->addr + SCI_BRR );
0098 
0099   return 0 ;
0100 }
0101 
0102 static void _sci_init(
0103   rtems_device_minor_number minor )
0104 {
0105   uint16_t      temp16 ;
0106 
0107   /* Pin function controller initialisation for asynchronous mode */
0108   if( minor == 0)
0109     {
0110       temp16 = read16( PFC_PBCR1);
0111       temp16 &= ~( PB8MD | PB9MD );
0112       temp16 |= (PB_TXD0 | PB_RXD0);
0113       write16( temp16, PFC_PBCR1);
0114     }
0115   else
0116     {
0117       temp16 = read16( PFC_PBCR1);
0118       temp16 &= ~( PB10MD | PB11MD);
0119       temp16 |= (PB_TXD1 | PB_RXD1);
0120       write16( temp16, PFC_PBCR1);
0121     }
0122 
0123   /* disable sck-pin */
0124   if( minor == 0)
0125   {
0126       temp16 = read16( PFC_PBCR1);
0127       temp16 &= ~(PB12MD);
0128       write16( temp16, PFC_PBCR1);
0129   }
0130   else
0131   {
0132       temp16 = read16( PFC_PBCR1);
0133       temp16 &= ~(PB13MD);
0134       write16( temp16, PFC_PBCR1);
0135   }
0136 }
0137 
0138 static void _sci_tx_polled(
0139   int minor,
0140   const char buf )
0141 {
0142   struct scidev_t *scidev = &sci_device[minor] ;
0143   int8_t           ssr ;
0144 
0145   while ( !inb((scidev->addr + SCI_SSR) & SCI_TDRE ))
0146       ;
0147   write8(buf,scidev->addr+SCI_TDR);
0148 
0149   ssr = inb(scidev->addr+SCI_SSR);
0150   ssr &= ~SCI_TDRE ;
0151   write8(ssr,scidev->addr+SCI_SSR);
0152 }
0153 
0154 static int _sci_rx_polled (
0155   int minor)
0156 {
0157   struct scidev_t *scidev = &sci_device[minor] ;
0158 
0159   unsigned char c;
0160   char ssr ;
0161   ssr = read8(scidev->addr + SCI_SSR) ;
0162 
0163   if (ssr & (SCI_PER | SCI_FER | SCI_ORER))
0164     write8(ssr & ~(SCI_PER | SCI_FER | SCI_ORER), scidev->addr+SCI_SSR);
0165 
0166   if ( !(ssr & SCI_RDRF) )
0167     return -1;
0168 
0169   c = read8(scidev->addr + SCI_RDR) ;
0170 
0171   write8(ssr & ~SCI_RDRF,scidev->addr + SCI_SSR);
0172   return c;
0173 }
0174 
0175 /*
0176  * sci_initialize
0177  */
0178 
0179 rtems_device_driver sh_sci_initialize(
0180   rtems_device_major_number  major,
0181   rtems_device_minor_number  minor,
0182   void                      *arg )
0183 {
0184   rtems_device_driver status ;
0185   rtems_device_minor_number     i;
0186 
0187   /*
0188    * register all possible devices.
0189    * the initialization of the hardware is done by sci_open
0190    */
0191 
0192   for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
0193   {
0194     status = rtems_io_register_name(
0195       sci_device[i].name,
0196       major,
0197       sci_device[i].minor );
0198     if (status != RTEMS_SUCCESSFUL)
0199       rtems_fatal_error_occurred(status);
0200   }
0201 
0202   /* default hardware setup */
0203 
0204   return RTEMS_SUCCESSFUL;
0205 }
0206 
0207 
0208 /*
0209  *  Open entry point
0210  */
0211 
0212 rtems_device_driver sh_sci_open(
0213   rtems_device_major_number major,
0214   rtems_device_minor_number minor,
0215   void                    * arg )
0216 {
0217   uint8_t   temp8;
0218 
0219  /* check for valid minor number */
0220    if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
0221    {
0222      return RTEMS_INVALID_NUMBER;
0223    }
0224 
0225  /* device already opened */
0226   if ( sci_device[minor].opened > 0 )
0227   {
0228     sci_device[minor].opened++ ;
0229     return RTEMS_SUCCESSFUL ;
0230   }
0231 
0232   _sci_init( minor );
0233 
0234   if (minor == 0) {
0235     temp8 = read8(sci_device[minor].addr + SCI_SCR);
0236     temp8 &= ~(SCI_TE | SCI_RE) ;
0237     write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
0238     _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags, sci_device[minor].spd );
0239 
0240 /* FIXME: Should be one bit delay */
0241     CPU_delay(50000); /* microseconds */
0242 
0243     temp8 |= SCI_RE | SCI_TE;
0244     write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Enable clock output */
0245   } else {
0246     temp8 = read8(sci_device[minor].addr + SCI_SCR);
0247     temp8 &= ~(SCI_TE | SCI_RE) ;
0248     write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Clear SCR */
0249     _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags, sci_device[minor].spd );
0250 
0251 /* FIXME: Should be one bit delay */
0252     CPU_delay(50000); /* microseconds */
0253 
0254     temp8 |= SCI_RE | SCI_TE;
0255     write8(temp8, sci_device[minor].addr + SCI_SCR);    /* Enable clock output */
0256   }
0257 
0258   sci_device[minor].opened++ ;
0259 
0260   return RTEMS_SUCCESSFUL ;
0261 }
0262 
0263 /*
0264  *  Close entry point
0265  */
0266 
0267 rtems_device_driver sh_sci_close(
0268   rtems_device_major_number major,
0269   rtems_device_minor_number minor,
0270   void                    * arg
0271 )
0272 {
0273   if( sci_device[minor].opened == 0 )
0274     {
0275       return RTEMS_INVALID_NUMBER;
0276     }
0277 
0278   sci_device[minor].opened-- ;
0279 
0280   return RTEMS_SUCCESSFUL ;
0281 }
0282 
0283 /*
0284  * read bytes from the serial port.
0285  */
0286 
0287 rtems_device_driver sh_sci_read(
0288   rtems_device_major_number major,
0289   rtems_device_minor_number minor,
0290   void                    * arg
0291 )
0292 {
0293   int count = 0;
0294 
0295   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
0296   char * buffer = rw_args->buffer;
0297   int maximum = rw_args->count;
0298 
0299   for (count = 0; count < maximum; count++) {
0300     buffer[ count ] = _sci_rx_polled(minor);
0301     if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
0302       buffer[ count++ ]  = '\n';
0303       break;
0304     }
0305   }
0306 
0307   rw_args->bytes_moved = count;
0308   return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
0309 }
0310 
0311 /*
0312  * write bytes to the serial port.
0313  */
0314 
0315 rtems_device_driver sh_sci_write(
0316   rtems_device_major_number major,
0317   rtems_device_minor_number minor,
0318   void                    * arg
0319 )
0320 {
0321   int count;
0322 
0323   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
0324   char *buffer = rw_args->buffer;
0325   int maximum = rw_args->count;
0326 
0327   for (count = 0; count < maximum; count++) {
0328 #if 0
0329     if ( buffer[ count ] == '\n') {
0330       outbyte(minor, '\r');
0331     }
0332 #endif
0333     _sci_tx_polled( minor, buffer[ count ] );
0334   }
0335 
0336   rw_args->bytes_moved = maximum;
0337   return 0;
0338 }
0339 
0340 /*
0341  *  IO Control entry point
0342  */
0343 
0344 rtems_device_driver sh_sci_control(
0345   rtems_device_major_number major,
0346   rtems_device_minor_number minor,
0347   void                    * arg
0348 )
0349 {
0350   /* Not yet supported */
0351   return RTEMS_SUCCESSFUL ;
0352 }