source: rtems/c/src/lib/libcpu/sh/sh7045/sci/sci_termios.c @ 2afd852a

4.104.114.84.95
Last change on this file since 2afd852a was 2afd852a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/05 at 18:48:32

2005-05-03 Joel Sherrill <joel@…>

  • sh7045/sci/sci.c, sh7045/sci/sci_termios.c: Remove warnings.
  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[3a5fec8]1/*
2 * Termios console serial driver.
3 *
4 * Based on SCI driver by Ralf Corsepius and John M. Mills
5 *
6 * Author: Radzislaw Galler <rgaller@et.put.poznan.pl>
7 *
8 *  COPYRIGHT (c) 1989-2001.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
[85a18cc]13 *  http://www.rtems.com/license/LICENSE.
[3a5fec8]14 *
15 * $Id$
16 *
17 */
18
19#include <bsp.h>
20#include <stdlib.h>
21
22#include <libchip/serial.h>
23#include <libchip/sersupp.h>
24
25#include <rtems/libio.h>
[c0a200e]26#include <rtems/iosupp.h>
[3a5fec8]27
28#include <rtems/score/sh_io.h>
29#include <rtems/score/ispsh7045.h>
30#include <rtems/score/iosh7045.h>
31
32#include <sh/sh7_sci.h>
33#include <sh/sh7_pfc.h>
34#include <sh/sci_termios.h>
35
36
[3906b3ea]37/*
[3a5fec8]38 * Some handy macros
39 */
40#define SH_SCI_REG_DATA(_data, _minor, _register) \
41 (write8(_data, Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
42
43#define SH_SCI_REG_FLAG(_flag, _minor, _register) \
44 (write8(read8(Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)) | (_flag), \
45         Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
46
47#define SH_SCI_REG_MASK(_flag, _minor, _register) \
48 (write8(read8(Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)) & ~(_flag), \
49         Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
50
51/*
52 * NOTE: Some SH variants have 3 sci devices
53 */
[3906b3ea]54
[3a5fec8]55#define SCI_MINOR_DEVICES       2
56
57
[3906b3ea]58/*
59 * Automatically generated function imported from scitab.rel
[3a5fec8]60 */
61extern int _sci_get_brparms(
62  tcflag_t      cflag,
63  unsigned char *smr,
[2afd852a]64  unsigned char *brr
65);
[3a5fec8]66
[3906b3ea]67/*
[3a5fec8]68 * Translate termios flags into SCI settings
69 */
[3906b3ea]70int sh_sci_set_attributes(
[3a5fec8]71  int minor,
72  const struct termios *t
73)
74{
[2afd852a]75    uint8_t     smr;
76    uint8_t     brr;
[3a5fec8]77    int a;
[3906b3ea]78
[3a5fec8]79    tcflag_t c_cflag = t->c_cflag;
80
[2afd852a]81    if ( c_cflag & CBAUD ) {
[3a5fec8]82        if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
83            return -1 ;
84    }
[3906b3ea]85
[2afd852a]86    if ( c_cflag & CSIZE ) {
[3a5fec8]87        if ( c_cflag & CS8 )
88            smr &= ~SCI_SEVEN_BIT_DATA;
89        else if ( c_cflag & CS7 )
90            smr |= SCI_SEVEN_BIT_DATA;
91        else
92            return -1 ;
93    }
94
95    if ( c_cflag & CSTOPB )
96        smr |= SCI_STOP_BITS_2;
97    else
98        smr &= ~SCI_STOP_BITS_2;
99
100    if ( c_cflag & PARENB )
101        smr |= SCI_PARITY_ON ;
102    else
103        smr &= ~SCI_PARITY_ON ;
104
105    if ( c_cflag & PARODD )
106        smr |= SCI_ODD_PARITY ;
107    else
108        smr &= ~SCI_ODD_PARITY;
109
110    SH_SCI_REG_MASK((SCI_RE | SCI_TE), minor, SCI_SCR);
[3906b3ea]111
[3a5fec8]112    SH_SCI_REG_DATA(smr, minor, SCI_SMR);
113    SH_SCI_REG_DATA(brr, minor, SCI_BRR);
[3906b3ea]114
[2afd852a]115    for (a=0; a < 10000L; a++) { /* Delay one bit */
[3a5fec8]116        asm volatile ("nop");
117    }
118
119    SH_SCI_REG_FLAG((SCI_RE | SCI_TE), minor, SCI_SCR);
[3906b3ea]120
[3a5fec8]121    return 0;
122}
123
[3906b3ea]124/*
[3a5fec8]125 * Receive-data-full ISR
126 *
[3906b3ea]127 * The same routine for all interrupt sources of the same type.
[3a5fec8]128 */
129rtems_isr sh_sci_rx_isr(rtems_vector_number vector)
130{
131    int minor;
[3906b3ea]132
[2afd852a]133    for (minor = 0; minor < Console_Port_Count; minor++) {
134        if (Console_Port_Tbl[minor].ulIntVector == vector) {
135            char   temp8;
[3906b3ea]136
[3a5fec8]137            /*
138             * FIXME: error handling should be added
139             */
140            temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
141
142            rtems_termios_enqueue_raw_characters(
[2afd852a]143                Console_Port_Data[minor].termios_data, &temp8, 1);
[3a5fec8]144
145            SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
146            break;
147        }
148    }
149}
150
[3906b3ea]151/*
[3a5fec8]152 * Transmit-data-empty ISR
153 *
154 * The same routine for all interrupt sources of the same type.
155 */
156rtems_isr sh_sci_tx_isr(rtems_vector_number vector)
157{
158    int minor;
159
[2afd852a]160    for (minor = 0; minor < Console_Port_Count; minor++) {
161        if (Console_Port_Tbl[minor].ulDataPort == vector) {
[3906b3ea]162            /*
[3a5fec8]163             * FIXME: Error handling should be added
164             */
[3906b3ea]165
166            /*
[3a5fec8]167             * Mask end-of-transmission interrupt
168             */
169            SH_SCI_REG_MASK(SCI_TIE, minor, SCI_SCR);
170
[2afd852a]171            if (rtems_termios_dequeue_characters(
172                   Console_Port_Data[minor].termios_data, 1)) {
[3906b3ea]173                /*
[3a5fec8]174                 * More characters to be received - interrupt must be enabled
175                 */
176                SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
177            }
178            break;
179        }
180    }
181}
182
183
[3906b3ea]184/*
[3a5fec8]185 * Initialization of serial port
186 */
187void sh_sci_init(int minor)
188{
[e96a950b]189    uint16_t   temp16;
[3906b3ea]190
191    /*
192     * set PFC registers to enable I/O pins
[3a5fec8]193     */
[2afd852a]194    if ((minor == 0)) {
[3a5fec8]195        temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */
196        temp16 &= ~(PA2MD1 | PA2MD0);
197        temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */
198        write16(temp16, PFC_PACRL2);
[3906b3ea]199
[2afd852a]200    } else if (minor == 1) {
[3a5fec8]201        temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */
202        temp16 &= ~(PA5MD1 | PA5MD0);
203        temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */
204        write16(temp16, PFC_PACRL2);
[3906b3ea]205    }
[3a5fec8]206
[3906b3ea]207    /*
[3a5fec8]208     * Non-default hardware setup occurs in sh_sci_first_open
209     */
210}
211
[3906b3ea]212/*
[3a5fec8]213 * Initialization of interrupts
214 *
215 * Interrupts can be started only after opening a device, so interrupt
216 * flags are set up in sh_sci_first_open function
217 */
218void sh_sci_initialize_interrupts(int minor)
219{
220    rtems_isr_entry old_isr;
221    rtems_status_code status;
222
223    sh_sci_init(minor);
[3906b3ea]224    /*
[3a5fec8]225     * Disable IRQ of SCIx
226     */
[2afd852a]227    status = sh_set_irq_priority( Console_Port_Tbl[minor].ulIntVector, 0);
[3a5fec8]228
[2afd852a]229    if (status != RTEMS_SUCCESSFUL)
[3a5fec8]230        rtems_fatal_error_occurred(status);
231
232    SH_SCI_REG_MASK(SCI_RIE, minor, SCI_SCR);
233
[3906b3ea]234    /*
[3a5fec8]235     * Catch apropriate vectors
236     */
237    status = rtems_interrupt_catch(
[3906b3ea]238        sh_sci_rx_isr,
[3a5fec8]239        Console_Port_Tbl[minor].ulIntVector,
240        &old_isr);
241
[2afd852a]242    if (status != RTEMS_SUCCESSFUL)
[3a5fec8]243        rtems_fatal_error_occurred(status);
244
245    status = rtems_interrupt_catch(
246        sh_sci_tx_isr,
247        Console_Port_Tbl[minor].ulDataPort,
248        &old_isr);
249
[2afd852a]250    if (status != RTEMS_SUCCESSFUL)
[3a5fec8]251        rtems_fatal_error_occurred(status);
[3906b3ea]252
253    /*
254     * Enable IRQ of SCIx
[3a5fec8]255     */
256    SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
257
258    status = sh_set_irq_priority(
[3906b3ea]259        Console_Port_Tbl[minor].ulIntVector,
[3a5fec8]260        Console_Port_Tbl[minor].ulCtrlPort2);
261
[2afd852a]262    if (status != RTEMS_SUCCESSFUL)
[3a5fec8]263        rtems_fatal_error_occurred(status);
264}
265
266
267/*
268 *  Open entry point
269 *   Sets up port and pins for selected sci.
270 */
271
272int sh_sci_first_open(
273  int major,
274  int minor,
[2afd852a]275  void *arg
276)
[3a5fec8]277{
[2afd852a]278    char   temp8;
[3a5fec8]279    unsigned int a ;
[3906b3ea]280
281    /*
282     * check for valid minor number
[3a5fec8]283     */
[2afd852a]284    if (( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 )) {
[3a5fec8]285        return RTEMS_INVALID_NUMBER;
286    }
287
[3906b3ea]288    /*
289     * set up SCI registers
[3a5fec8]290     */
291    /* Clear SCR - disable Tx and Rx */
292    SH_SCI_REG_DATA(0x00, minor, SCI_SCR);
[3906b3ea]293
[3a5fec8]294    /* set SMR and BRR - baudrate and format */
295    sh_sci_set_attributes(minor, Console_Port_Tbl[minor].pDeviceParams);
296
[2afd852a]297    for (a=0; a < 10000L; a++) {                      /* Delay */
[3a5fec8]298        asm volatile ("nop");
299    }
300
301    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */
302           Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SCR);
303
[3906b3ea]304    /*
305     * clear error flags
[3a5fec8]306     */
307    temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
[2afd852a]308    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)) {
[3a5fec8]309        /* flush input */
310        temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
311
312        /* clear some flags */
313        SH_SCI_REG_FLAG((SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
[3906b3ea]314
[3a5fec8]315        /* check if everything is OK */
316        temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
[3906b3ea]317    }
318
[3a5fec8]319    /* Clear RDRF flag */
320    SH_SCI_REG_DATA(0x00, minor, SCI_TDR); /* force output */
[3906b3ea]321
[3a5fec8]322    /* Clear the TDRE bit */
323    SH_SCI_REG_FLAG(SCI_TDRE, minor, SCI_SSR);
[3906b3ea]324
325    /*
326     * Interrupt setup
[3a5fec8]327     */
[2afd852a]328    if (Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts) {
[3a5fec8]329        SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
330    }
[3906b3ea]331
[3a5fec8]332    return RTEMS_SUCCESSFUL ;
333}
334
335/*
336 *  Close entry point
337 */
338
339int sh_sci_last_close(
340  int major,
341  int minor,
342  void *arg
343)
344{
345    /* FIXME: Incomplete */
346
347    /* Shutdown interrupts if necessary */
[2afd852a]348    if (Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts)
[3a5fec8]349    {
350        SH_SCI_REG_MASK((SCI_TIE | SCI_RIE), minor, SCI_SCR);
351    }
352    return RTEMS_SUCCESSFUL ;
353}
354
[3906b3ea]355/*
[3a5fec8]356 * Interrupt aware write routine
357 */
358int sh_sci_write_support_int(
[2afd852a]359  int            minor,
360  const char    *buf,
361  int            len
[3a5fec8]362)
363{
[2afd852a]364    if (!len)
[3a5fec8]365        return 0;
366    /*
367     * Put data into TDR and clear transmission-end-flag
368     */
369    SH_SCI_REG_DATA(*buf, minor, SCI_TDR);
370    SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
[3906b3ea]371    /*
[3a5fec8]372     * Enable interrupt
373     */
374    SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
[3906b3ea]375
[3a5fec8]376    return 1;
377}
378
[3906b3ea]379/*
[3a5fec8]380 * Polled write method
381 */
382int sh_sci_write_support_polled(
[2afd852a]383  int            minor,
384  const char    *buf,
385  int            len
[3a5fec8]386)
387{
388    int count = 0;
[3906b3ea]389
[2afd852a]390    while(count < len) {
[3a5fec8]391        sh_sci_write_polled(minor, buf[count]);
392        count++;
393    }
[3906b3ea]394    /*
[3a5fec8]395     * Return number of bytes written
396     */
397    return count;
398}
399
[3906b3ea]400/*
[3a5fec8]401 * Polled write of one character at a time
402 */
403void sh_sci_write_polled(
[2afd852a]404  int     minor,
405  char    c
[3a5fec8]406)
407{
[3906b3ea]408    /*
[3a5fec8]409     * Wait for end of previous character
410     */
411    while(!(read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_TDRE));
[3906b3ea]412    /*
[3a5fec8]413     * Send the character
414     */
415    SH_SCI_REG_DATA(c, minor, SCI_TDR);
[3906b3ea]416
417    /*
[3a5fec8]418     * Clear TDRE flag
419     */
420    SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
421}
422
[3906b3ea]423/*
424 * Non-blocking read
[3a5fec8]425 */
426int sh_sci_inbyte_nonblocking_polled(int minor)
427{
[2afd852a]428    char   inbyte;
[3a5fec8]429
[3906b3ea]430    /*
[3a5fec8]431     * Check if input buffer is full
432     */
[2afd852a]433    if (read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_RDRF) {
[3a5fec8]434        inbyte = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
435        SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
[3906b3ea]436
437        /*
[3a5fec8]438         * Check for errors
439         */
[2afd852a]440        if (read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) &
441           (SCI_ORER | SCI_FER | SCI_PER)) {
[3a5fec8]442            SH_SCI_REG_MASK((SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
443            return -1;
[3906b3ea]444        }
[3a5fec8]445        return (int)inbyte;
446    }
447    return -1;
448}
Note: See TracBrowser for help on using the repository browser.