source: rtems/c/src/lib/libbsp/sh/gensh2/console/sci_termios.c @ 533e2c0

5
Last change on this file since 533e2c0 was 533e2c0, checked in by Sebastian Huber <sebastian.huber@…>, on 12/08/17 at 12:31:12

bsp/gensh2: Move libcpu files to BSP

Update #3254.

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