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

4.104.11
Last change on this file since a5fb3d1b was a5fb3d1b, checked in by Ralf Corsepius <ralf.corsepius@…>, on Apr 15, 2010 at 8:39:26 AM

Reflect termios API changes.

  • Property mode set to 100644
File size: 9.9 KB
Line 
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
13 *  http://www.rtems.com/license/LICENSE.
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>
26#include <rtems/iosupp.h>
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
37/*
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 */
54
55#define SCI_MINOR_DEVICES       2
56
57
58/*
59 * Automatically generated function imported from scitab.rel
60 */
61extern int _sci_get_brparms(
62  tcflag_t      cflag,
63  unsigned char *smr,
64  unsigned char *brr
65);
66
67/*
68 * Translate termios flags into SCI settings
69 */
70int sh_sci_set_attributes(
71  int minor,
72  const struct termios *t
73)
74{
75    uint8_t     smr;
76    uint8_t     brr;
77    int a;
78
79    tcflag_t c_cflag = t->c_cflag;
80
81    if ( c_cflag & CBAUD ) {
82        if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
83            return -1 ;
84    }
85
86    if ( c_cflag & CSIZE ) {
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);
111
112    SH_SCI_REG_DATA(smr, minor, SCI_SMR);
113    SH_SCI_REG_DATA(brr, minor, SCI_BRR);
114
115    for (a=0; a < 10000L; a++) { /* Delay one bit */
116        asm volatile ("nop");
117    }
118
119    SH_SCI_REG_FLAG((SCI_RE | SCI_TE), minor, SCI_SCR);
120
121    return 0;
122}
123
124/*
125 * Receive-data-full ISR
126 *
127 * The same routine for all interrupt sources of the same type.
128 */
129rtems_isr sh_sci_rx_isr(rtems_vector_number vector)
130{
131    int minor;
132
133    for (minor = 0; minor < Console_Port_Count; minor++) {
134        if (Console_Port_Tbl[minor].ulIntVector == vector) {
135            char   temp8;
136
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(
143                Console_Port_Data[minor].termios_data, &temp8, 1);
144
145            SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
146            break;
147        }
148    }
149}
150
151/*
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
160    for (minor = 0; minor < Console_Port_Count; minor++) {
161        if (Console_Port_Tbl[minor].ulDataPort == vector) {
162            /*
163             * FIXME: Error handling should be added
164             */
165
166            /*
167             * Mask end-of-transmission interrupt
168             */
169            SH_SCI_REG_MASK(SCI_TIE, minor, SCI_SCR);
170
171            if (rtems_termios_dequeue_characters(
172                   Console_Port_Data[minor].termios_data, 1)) {
173                /*
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
184/*
185 * Initialization of serial port
186 */
187void sh_sci_init(int minor)
188{
189    uint16_t   temp16;
190
191    /*
192     * set PFC registers to enable I/O pins
193     */
194    if ((minor == 0)) {
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);
199
200    } else if (minor == 1) {
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);
205    }
206
207    /*
208     * Non-default hardware setup occurs in sh_sci_first_open
209     */
210}
211
212/*
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);
224    /*
225     * Disable IRQ of SCIx
226     */
227    status = sh_set_irq_priority( Console_Port_Tbl[minor].ulIntVector, 0);
228
229    if (status != RTEMS_SUCCESSFUL)
230        rtems_fatal_error_occurred(status);
231
232    SH_SCI_REG_MASK(SCI_RIE, minor, SCI_SCR);
233
234    /*
235     * Catch apropriate vectors
236     */
237    status = rtems_interrupt_catch(
238        sh_sci_rx_isr,
239        Console_Port_Tbl[minor].ulIntVector,
240        &old_isr);
241
242    if (status != RTEMS_SUCCESSFUL)
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
250    if (status != RTEMS_SUCCESSFUL)
251        rtems_fatal_error_occurred(status);
252
253    /*
254     * Enable IRQ of SCIx
255     */
256    SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
257
258    status = sh_set_irq_priority(
259        Console_Port_Tbl[minor].ulIntVector,
260        Console_Port_Tbl[minor].ulCtrlPort2);
261
262    if (status != RTEMS_SUCCESSFUL)
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,
275  void *arg
276)
277{
278    char   temp8;
279    unsigned int a ;
280
281    /*
282     * check for valid minor number
283     */
284    if (( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 )) {
285        return RTEMS_INVALID_NUMBER;
286    }
287
288    /*
289     * set up SCI registers
290     */
291    /* Clear SCR - disable Tx and Rx */
292    SH_SCI_REG_DATA(0x00, minor, SCI_SCR);
293
294    /* set SMR and BRR - baudrate and format */
295    sh_sci_set_attributes(minor, Console_Port_Tbl[minor].pDeviceParams);
296
297    for (a=0; a < 10000L; a++) {                      /* Delay */
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
304    /*
305     * clear error flags
306     */
307    temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
308    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)) {
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);
314
315        /* check if everything is OK */
316        temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
317    }
318
319    /* Clear RDRF flag */
320    SH_SCI_REG_DATA(0x00, minor, SCI_TDR); /* force output */
321
322    /* Clear the TDRE bit */
323    SH_SCI_REG_FLAG(SCI_TDRE, minor, SCI_SSR);
324
325    /*
326     * Interrupt setup
327     */
328    if (Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts) {
329        SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
330    }
331
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 */
348    if (Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts)
349    {
350        SH_SCI_REG_MASK((SCI_TIE | SCI_RIE), minor, SCI_SCR);
351    }
352    return RTEMS_SUCCESSFUL ;
353}
354
355/*
356 * Interrupt aware write routine
357 */
358ssize_t sh_sci_write_support_int(
359  int            minor,
360  const char    *buf,
361  size_t         len
362)
363{
364    if (!len)
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);
371    /*
372     * Enable interrupt
373     */
374    SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
375
376    return 1;
377}
378
379/*
380 * Polled write method
381 */
382ssize_t sh_sci_write_support_polled(
383  int            minor,
384  const char    *buf,
385  size_t         len
386)
387{
388    int count = 0;
389
390    while(count < len) {
391        sh_sci_write_polled(minor, buf[count]);
392        count++;
393    }
394    /*
395     * Return number of bytes written
396     */
397    return count;
398}
399
400/*
401 * Polled write of one character at a time
402 */
403void sh_sci_write_polled(
404  int     minor,
405  char    c
406)
407{
408    /*
409     * Wait for end of previous character
410     */
411    while(!(read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_TDRE));
412    /*
413     * Send the character
414     */
415    SH_SCI_REG_DATA(c, minor, SCI_TDR);
416
417    /*
418     * Clear TDRE flag
419     */
420    SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
421}
422
423/*
424 * Non-blocking read
425 */
426int sh_sci_inbyte_nonblocking_polled(int minor)
427{
428    char   inbyte;
429
430    /*
431     * Check if input buffer is full
432     */
433    if (read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_RDRF) {
434        inbyte = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
435        SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
436
437        /*
438         * Check for errors
439         */
440        if (read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) &
441           (SCI_ORER | SCI_FER | SCI_PER)) {
442            SH_SCI_REG_MASK((SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
443            return -1;
444        }
445        return (int)inbyte;
446    }
447    return -1;
448}
Note: See TracBrowser for help on using the repository browser.